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 _I_HostDBProcessor_h_
00025 #define _I_HostDBProcessor_h_
00026
00027 #include "I_EventSystem.h"
00028 #include "SRV.h"
00029
00030
00031 #define EVENT_HOST_DB_LOOKUP (HOSTDB_EVENT_EVENTS_START+0)
00032 #define EVENT_HOST_DB_IP_REMOVED (HOSTDB_EVENT_EVENTS_START+1)
00033 #define EVENT_HOST_DB_GET_RESPONSE (HOSTDB_EVENT_EVENTS_START+2)
00034
00035 #define EVENT_SRV_LOOKUP (SRV_EVENT_EVENTS_START+0)
00036 #define EVENT_SRV_IP_REMOVED (SRV_EVENT_EVENTS_START+1)
00037 #define EVENT_SRV_GET_RESPONSE (SRV_EVENT_EVENTS_START+2)
00038
00039 #define HOST_DB_MAX_ROUND_ROBIN_INFO 16
00040
00041 #define HOST_DB_SRV_PREFIX "_http._tcp."
00042
00043
00044
00045 struct HostDBContinuation;
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 extern int hostdb_enable;
00056 extern unsigned int hostdb_current_interval;
00057 extern unsigned int hostdb_ip_stale_interval;
00058 extern unsigned int hostdb_ip_timeout_interval;
00059 extern unsigned int hostdb_ip_fail_timeout_interval;
00060 extern unsigned int hostdb_serve_stale_but_revalidate;
00061
00062
00063 static inline unsigned int
00064 makeHostHash(const char *string)
00065 {
00066 ink_assert(string && *string);
00067 if (!string || *string == 0)
00068 return 0;
00069
00070 const uint32_t InitialFNV = 2166136261U;
00071 const int32_t FNVMultiple = 16777619;
00072
00073 uint64_t hash = InitialFNV;
00074 uint32_t *p = (uint32_t *) &hash;
00075 while(*string) {
00076 p[0] = p[0] ^ (toupper(*string));
00077 hash = (p[1] ^ p[0]) * FNVMultiple;
00078 ++string;
00079 }
00080 return (p[1] ^ p[0]);
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 union HostDBApplicationInfo
00094 {
00095 struct application_data_allotment
00096 {
00097 unsigned int application1;
00098 unsigned int application2;
00099 } allotment;
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 struct http_server_attr
00115 {
00116 unsigned int http_version:3;
00117 unsigned int pipeline_max:7;
00118 unsigned int keepalive_timeout:6;
00119 unsigned int fail_count:8;
00120 unsigned int unused1:8;
00121 unsigned int last_failure:32;
00122 } http_data;
00123
00124 enum HttpVersion_t
00125 {
00126 HTTP_VERSION_UNDEFINED = 0,
00127 HTTP_VERSION_09 = 1,
00128 HTTP_VERSION_10 = 2,
00129 HTTP_VERSION_11 = 3
00130 };
00131
00132 struct application_data_rr
00133 {
00134 int offset;
00135 } rr;
00136 };
00137
00138 struct HostDBRoundRobin;
00139
00140 struct SRVInfo
00141 {
00142 unsigned int srv_offset:16;
00143 unsigned int srv_weight:16;
00144 unsigned int srv_priority:16;
00145 unsigned int srv_port:16;
00146 unsigned int key;
00147 };
00148
00149 struct HostDBInfo
00150 {
00151
00152
00153
00154 sockaddr* ip() { return &data.ip.sa; }
00155 sockaddr const* ip() const { return &data.ip.sa; }
00156
00157 char *hostname();
00158 char *srvname(HostDBRoundRobin *rr);
00159 HostDBRoundRobin *rr();
00160
00161
00162 void bad() { full = 0; }
00163
00164
00165
00166
00167
00168
00169
00170 HostDBApplicationInfo app;
00171
00172 unsigned int ip_interval()
00173 {
00174 return (hostdb_current_interval - ip_timestamp) & 0x7FFFFFFF;
00175 }
00176
00177 int ip_time_remaining()
00178 {
00179 return (int) ip_timeout_interval - (int) ((hostdb_current_interval - ip_timestamp) & 0x7FFFFFFF);
00180 }
00181
00182 bool is_ip_stale() {
00183 if (ip_timeout_interval >= 2 * hostdb_ip_stale_interval)
00184 return ip_interval() >= hostdb_ip_stale_interval;
00185 else
00186 return false;
00187 }
00188
00189 bool is_ip_timeout() {
00190 return ip_interval() >= ip_timeout_interval;
00191 }
00192
00193 bool is_ip_fail_timeout() {
00194 return ip_interval() >= hostdb_ip_fail_timeout_interval;
00195 }
00196
00197 void refresh_ip()
00198 {
00199 ip_timestamp = hostdb_current_interval;
00200 }
00201
00202 bool serve_stale_but_revalidate() {
00203
00204 if (hostdb_serve_stale_but_revalidate <= 0)
00205 return false;
00206
00207
00208
00209
00210 if ((ip_timeout_interval + hostdb_serve_stale_but_revalidate) > ip_interval()) {
00211 Debug("hostdb", "serving stale entry %d | %d | %d as requested by config",
00212 ip_timeout_interval, hostdb_serve_stale_but_revalidate, ip_interval());
00213 return true;
00214 }
00215
00216 return false;
00217 }
00218
00219
00220
00221
00222
00223
00224 union {
00225 IpEndpoint ip;
00226 int hostname_offset;
00227 SRVInfo srv;
00228 } data;
00229
00230 unsigned int ip_timestamp;
00231
00232 unsigned int ip_timeout_interval:31;
00233
00234 unsigned int full:1;
00235 unsigned int backed:1;
00236 unsigned int deleted:1;
00237 unsigned int hits:3;
00238
00239 unsigned int is_srv:1;
00240 unsigned int round_robin:1;
00241 unsigned int reverse_dns:1;
00242
00243 unsigned int md5_low_low:24;
00244 unsigned int md5_low;
00245
00246 uint64_t md5_high;
00247
00248 bool failed() {
00249 return !((is_srv && data.srv.srv_offset) || (reverse_dns && data.hostname_offset) || ats_is_ip(ip()));
00250 }
00251 void set_failed() {
00252 if (is_srv)
00253 data.srv.srv_offset = 0;
00254 else if (reverse_dns)
00255 data.hostname_offset = 0;
00256 else
00257 ats_ip_invalidate(ip());
00258 }
00259
00260 void set_deleted() { deleted = 1; }
00261 bool is_deleted() const { return deleted; }
00262
00263 bool is_empty() const { return !full; }
00264
00265 void set_empty()
00266 {
00267 full = 0;
00268 md5_high = 0;
00269 md5_low = 0;
00270 md5_low_low = 0;
00271 }
00272
00273 void set_full(uint64_t folded_md5, int buckets)
00274 {
00275 uint64_t ttag = folded_md5 / buckets;
00276
00277 if (!ttag)
00278 ttag = 1;
00279 md5_low_low = (unsigned int) ttag;
00280 md5_low = (unsigned int) (ttag >> 24);
00281 full = 1;
00282 }
00283
00284 void reset()
00285 {
00286 ats_ip_invalidate(ip());
00287 app.allotment.application1 = 0;
00288 app.allotment.application2 = 0;
00289 backed = 0;
00290 deleted = 0;
00291 hits = 0;
00292 round_robin = 0;
00293 reverse_dns = 0;
00294 is_srv = 0;
00295 }
00296
00297 uint64_t tag() {
00298 uint64_t f = md5_low;
00299 return (f << 24) + md5_low_low;
00300 }
00301
00302 bool match(INK_MD5 &, int, int);
00303 int heap_size();
00304 int *heap_offset_ptr();
00305 };
00306
00307
00308 struct HostDBRoundRobin
00309 {
00310
00311 short rrcount;
00312
00313
00314 short good;
00315
00316 unsigned short current;
00317 unsigned short length;
00318 ink_time_t timed_rr_ctime;
00319
00320 HostDBInfo info[];
00321
00322
00323
00324 static unsigned size(unsigned count, unsigned srv_len = 0)
00325 {
00326 ink_assert(count > 0);
00327 return INK_ALIGN((sizeof(HostDBRoundRobin) + (count * sizeof(HostDBInfo)) + srv_len), 8);
00328 }
00329
00330
00331
00332
00333 int index_of(sockaddr const* addr);
00334 HostDBInfo *find_ip(sockaddr const* addr);
00335
00336 HostDBInfo *find_target(const char *target);
00337
00338
00339
00340
00341 HostDBInfo* select_next(sockaddr const* addr);
00342 HostDBInfo *select_best_http(sockaddr const* client_ip, ink_time_t now, int32_t fail_window);
00343 HostDBInfo *select_best_srv(char *target, InkRand *rand, ink_time_t now, int32_t fail_window);
00344 HostDBRoundRobin()
00345 : rrcount(0), good(0), current(0), length(0), timed_rr_ctime(0)
00346 { }
00347
00348 };
00349
00350 struct HostDBCache;
00351
00352
00353
00354 typedef void (Continuation::*process_hostdb_info_pfn) (HostDBInfo * r);
00355 typedef void (Continuation::*process_srv_info_pfn) (HostDBInfo * r);
00356
00357
00358
00359 struct HostDBProcessor: public Processor
00360 {
00361 friend struct HostDBSyncer;
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 enum
00373 { HOSTDB_DO_NOT_FORCE_DNS = 0,
00374 HOSTDB_ROUND_ROBIN = 0,
00375 HOSTDB_FORCE_DNS_RELOAD = 1,
00376 HOSTDB_FORCE_DNS_ALWAYS = 2,
00377 HOSTDB_DO_NOT_ROUND_ROBIN = 4
00378 };
00379
00380
00381 struct Options {
00382 typedef Options self;
00383 int port;
00384 int flags;
00385 int timeout;
00386 HostResStyle host_res_style;
00387
00388 Options() : port(0), flags(HOSTDB_DO_NOT_FORCE_DNS), timeout(0), host_res_style(HOST_RES_IPV4)
00389 { }
00390
00391
00392 self& setFlags(int f) { flags = f; return *this; }
00393 };
00394
00395
00396 static Options const DEFAULT_OPTIONS;
00397
00398 HostDBProcessor()
00399 { }
00400
00401 inkcoreapi Action *getbyname_re(Continuation * cont, const char *hostname, int len, Options const& opt = DEFAULT_OPTIONS);
00402
00403 Action *getSRVbyname_imm(Continuation * cont, process_srv_info_pfn process_srv_info, const char *hostname, int len, Options const& opt = DEFAULT_OPTIONS);
00404
00405 Action *getbyname_imm(
00406 Continuation * cont,
00407 process_hostdb_info_pfn process_hostdb_info,
00408 const char *hostname,
00409 int len,
00410 Options const& opt = DEFAULT_OPTIONS
00411 );
00412
00413
00414
00415 Action *getbyaddr_re(Continuation * cont, sockaddr const* aip)
00416 {
00417 return getby(cont, NULL, 0, aip, false, HOST_RES_NONE, 0);
00418 }
00419
00420 #if 0
00421
00422
00423
00424
00425
00426
00427
00428 Action *failed_connect_on_ip_for_name(
00429 Continuation * cont,
00430 sockaddr const* aip,
00431 const char *hostname, int len = 0
00432 );
00433 #endif
00434
00435
00436 void setbyname_appinfo(char *hostname, int len, int port, HostDBApplicationInfo * app)
00437 {
00438 sockaddr_in addr;
00439 ats_ip4_set(&addr, INADDR_ANY, port);
00440 setby(hostname, len, ats_ip_sa_cast(&addr), app);
00441 }
00442
00443 void setbyaddr_appinfo(sockaddr const* addr, HostDBApplicationInfo * app) {
00444 this->setby(0, 0, addr, app);
00445 }
00446
00447 void setbyaddr_appinfo(in_addr_t ip, HostDBApplicationInfo * app)
00448 {
00449 sockaddr_in addr;
00450 ats_ip4_set(&addr, ip);
00451 this->setby(0, 0, ats_ip_sa_cast(&addr), app);
00452 }
00453
00454
00455 static int hostdb_strict_round_robin;
00456 static int hostdb_timed_round_robin;
00457
00458
00459
00460
00461
00462 int start(int no_of_additional_event_threads = 0, size_t stacksize = DEFAULT_STACKSIZE);
00463
00464
00465 HostDBCache *cache();
00466 private:
00467 Action *getby(
00468 Continuation * cont,
00469 const char *hostname, int len,
00470 sockaddr const* ip,
00471 bool aforce_dns, HostResStyle host_res_style, int timeout
00472 );
00473 public:
00474
00475
00476
00477
00478
00479 void setby(
00480 const char *hostname,
00481 int len,
00482 sockaddr const* aip,
00483 HostDBApplicationInfo * app
00484 );
00485
00486 void setby_srv(const char *hostname, int len, const char *target,
00487 HostDBApplicationInfo * app);
00488
00489 };
00490
00491 void run_HostDBTest();
00492
00493 extern inkcoreapi HostDBProcessor hostDBProcessor;
00494
00495 void ink_hostdb_init(ModuleVersion version);
00496
00497 #endif