• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ControlMatcher.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /*****************************************************************************
00025  *
00026  *  ControlMatcher.cc - Implementation of general purpose matcher
00027  *
00028  *
00029  ****************************************************************************/
00030 
00031 #include "ink_config.h"
00032 #include <sys/types.h>
00033 #include "Main.h"
00034 #include "ProxyConfig.h"
00035 #include "ControlMatcher.h"
00036 #include "CacheControl.h"
00037 #include "ParentSelection.h"
00038 #include "HostLookup.h"
00039 #include "HTTP.h"
00040 #include "URL.h"
00041 #include "P_EventSystem.h"
00042 #include "P_Net.h"
00043 #include "P_Cache.h"
00044 #include "P_SplitDNS.h"
00045 #include "congest/Congestion.h"
00046 
00047 /****************************************************************
00048  *   Place all template instantiations at the bottom of the file
00049  ****************************************************************/
00050 
00051 
00052 
00053 // HttpRequestData accessors
00054 //   Can not be inlined due being virtual functions
00055 //
00056 char *
00057 HttpRequestData::get_string()
00058 {
00059   char *str = hdr->url_string_get(NULL);
00060 
00061   if (str)
00062     unescapifyStr(str);
00063   return str;
00064 }
00065 
00066 const char *
00067 HttpRequestData::get_host()
00068 {
00069   return hostname_str;
00070 }
00071 
00072 sockaddr const*
00073 HttpRequestData::get_ip()
00074 {
00075   return &dest_ip.sa;
00076 }
00077 
00078 sockaddr const*
00079 HttpRequestData::get_client_ip()
00080 {
00081   return &src_ip.sa;
00082 }
00083 
00084 /*************************************************************
00085  *   Begin class HostMatcher
00086  *************************************************************/
00087 
00088 template<class Data, class Result> HostMatcher<Data, Result>::HostMatcher(const char *name, const char *filename)
00089   : data_array(NULL),
00090     array_len(-1),
00091     num_el(-1),
00092     matcher_name(name),
00093     file_name(filename)
00094 {
00095   host_lookup = new HostLookup(name);
00096 }
00097 
00098 template<class Data, class Result> HostMatcher<Data, Result>::~HostMatcher()
00099 {
00100   delete host_lookup;
00101   delete[]data_array;
00102 }
00103 
00104 //
00105 // template <class Data,class Result>
00106 // void HostMatcher<Data,Result>::Print()
00107 //
00108 //  Debugging Method
00109 //
00110 template<class Data, class Result> void HostMatcher<Data, Result>::Print()
00111 {
00112 
00113   printf("\tHost/Domain Matcher with %d elements\n", num_el);
00114   host_lookup->Print(PrintFunc);
00115 }
00116 
00117 //
00118 // template <class Data,class Result>
00119 // void HostMatcher<Data,Result>::PrintFunc(void* opaque_data)
00120 //
00121 //  Debugging Method
00122 //
00123 template<class Data, class Result> void HostMatcher<Data, Result>::PrintFunc(void *opaque_data)
00124 {
00125   Data *d = (Data *) opaque_data;
00126   d->Print();
00127 }
00128 
00129 // void HostMatcher<Data,Result>::AllocateSpace(int num_entries)
00130 //
00131 //  Allocates the the HostLeaf and Data arrays
00132 //
00133 template<class Data, class Result> void HostMatcher<Data, Result>::AllocateSpace(int num_entries)
00134 {
00135   // Should not have been allocated before
00136   ink_assert(array_len == -1);
00137 
00138   host_lookup->AllocateSpace(num_entries);
00139 
00140   data_array = new Data[num_entries];
00141 
00142   array_len = num_entries;
00143   num_el = 0;
00144 }
00145 
00146 // void HostMatcher<Data,Result>::Match(RequestData* rdata, Result* result)
00147 //
00148 //  Searches our tree and updates argresult for each element matching
00149 //    arg hostname
00150 //
00151 template<class Data, class Result> void HostMatcher<Data, Result>::Match(RequestData * rdata, Result * result)
00152 {
00153   void *opaque_ptr;
00154   Data *data_ptr;
00155   bool r;
00156 
00157   // Check to see if there is any work to do before makeing
00158   //   the stirng copy
00159   if (num_el <= 0) {
00160     return;
00161   }
00162 
00163   HostLookupState s;
00164 
00165   r = host_lookup->MatchFirst(rdata->get_host(), &s, &opaque_ptr);
00166 
00167   while (r == true) {
00168     ink_assert(opaque_ptr != NULL);
00169     data_ptr = (Data *) opaque_ptr;
00170     data_ptr->UpdateMatch(result, rdata);
00171 
00172     r = host_lookup->MatchNext(&s, &opaque_ptr);
00173   }
00174 }
00175 
00176 //
00177 // char* HostMatcher<Data,Result>::NewEntry(bool domain_record,
00178 //          char* match_data, char* match_info, int line_num)
00179 //
00180 //   Creates a new host/domain record
00181 //
00182 //   If successful, returns NULL
00183 //   If not, returns a pointer to malloc allocated error string
00184 //     that the caller MUST DEALLOCATE
00185 //
00186 template<class Data, class Result> char *HostMatcher<Data, Result>::NewEntry(matcher_line * line_info)
00187 {
00188   Data *cur_d;
00189   char *errBuf;
00190   char *match_data;
00191 
00192   // Make sure space has been allocated
00193   ink_assert(num_el >= 0);
00194   ink_assert(array_len >= 0);
00195 
00196   // Make sure we do not overrun the array;
00197   ink_assert(num_el < array_len);
00198 
00199   match_data = line_info->line[1][line_info->dest_entry];
00200 
00201   // Make sure that the line_info is not bogus
00202   ink_assert(line_info->dest_entry < MATCHER_MAX_TOKENS);
00203   ink_assert(match_data != NULL);
00204 
00205   // Remove our consumed label from the parsed line
00206   line_info->line[0][line_info->dest_entry] = 0;
00207   line_info->num_el--;
00208 
00209   // Fill in the parameter info
00210   cur_d = data_array + num_el;
00211   errBuf = cur_d->Init(line_info);
00212 
00213   if (errBuf != NULL) {
00214     // There was a problem so undo the effects this function
00215     memset(cur_d, 0, sizeof(Data));
00216     return errBuf;
00217   }
00218   // Fill in the matching info
00219   host_lookup->NewEntry(match_data, (line_info->type == MATCH_DOMAIN) ? true : false, cur_d);
00220 
00221   num_el++;
00222   return NULL;
00223 }
00224 
00225 /*************************************************************
00226  *   End class HostMatcher
00227  *************************************************************/
00228 
00229 //
00230 // UrlMatcher<Data,Result>::UrlMatcher()
00231 //
00232 template<class Data, class Result> UrlMatcher<Data, Result>::UrlMatcher(const char *name, const char *filename)
00233   : url_ht(NULL),
00234     num_el(-1),
00235     matcher_name(name),
00236     file_name(filename)
00237 {
00238   url_ht = ink_hash_table_create(InkHashTableKeyType_String);
00239 }
00240 
00241 //
00242 // UrlMatcher<Data,Result>::~UrlMatcher()
00243 //
00244 template<class Data, class Result> UrlMatcher<Data, Result>::~UrlMatcher()
00245 {
00246   ink_hash_table_destroy(url_ht);
00247   for (int i = 0; i < num_el; i++) {
00248     ats_free(url_str[i]);
00249   }
00250   delete[]url_str;
00251   delete[]url_value;
00252   delete[]data_array;
00253 }
00254 
00255 //
00256 // void UrlMatcher<Data,Result>::Print()
00257 //
00258 //   Debugging function
00259 //
00260 template<class Data, class Result> void UrlMatcher<Data, Result>::Print()
00261 {
00262   printf("\tUrl Matcher with %d elements\n", num_el);
00263   for (int i = 0; i < num_el; i++) {
00264     printf("\t\tUrl: %s\n", url_str[i]);
00265     data_array[i].Print();
00266   }
00267 }
00268 
00269 //
00270 // void UrlMatcher<Data,Result>::AllocateSpace(int num_entries)
00271 //
00272 template<class Data, class Result> void UrlMatcher<Data, Result>::AllocateSpace(int num_entries)
00273 {
00274   // Should not have been allocated before
00275   ink_assert(array_len == -1);
00276 
00277   data_array = new Data[num_entries];
00278   url_value = new int [num_entries];
00279   url_str = new char *[num_entries];
00280   memset(url_str, 0, sizeof(char *) * num_entries);
00281   array_len = num_entries;
00282   num_el = 0;
00283 }
00284 
00285 //
00286 // char* UrlMatcher<Data,Result>::NewEntry(matcher_line* line_info)
00287 //
00288 template<class Data, class Result> char *UrlMatcher<Data, Result>::NewEntry(matcher_line * line_info)
00289 {
00290   Data *cur_d;
00291   char *errBuf;
00292   char *pattern;
00293   int *value;
00294 
00295   // Make sure space has been allocated
00296   ink_assert(num_el >= 0);
00297   ink_assert(array_len >= 0);
00298 
00299   // Make sure we do not overrun the array;
00300   ink_assert(num_el < array_len);
00301 
00302   pattern = line_info->line[1][line_info->dest_entry];
00303   // Make sure that the line_info is not bogus
00304   ink_assert(line_info->dest_entry < MATCHER_MAX_TOKENS);
00305   ink_assert(pattern != NULL);
00306 
00307   if (ink_hash_table_lookup(url_ht, pattern, (void **)&value)) {
00308     errBuf = (char *)ats_malloc(1024 * sizeof(char));
00309     *errBuf = '\0';
00310     snprintf(errBuf, 1024, "%s url expression error(have exist) at line %d position",
00311                  matcher_name, line_info->line_num);
00312     return errBuf;
00313   }
00314   
00315   // Remove our consumed label from the parsed line
00316   line_info->line[0][line_info->dest_entry] = 0;
00317   line_info->num_el--;
00318 
00319   // Fill in the parameter info
00320   cur_d = data_array + num_el;
00321   errBuf = cur_d->Init(line_info);
00322 
00323   if (errBuf == NULL) {
00324     url_str[num_el] = ats_strdup(pattern);
00325     url_value[num_el] = num_el;
00326     ink_hash_table_insert(url_ht, url_str[num_el], (void *)&url_value[num_el]);
00327     num_el++;
00328   }
00329   return errBuf;
00330 }
00331 
00332 //
00333 // void UrlMatcher<Data,Result>::Match(RD* rdata, Result* result)
00334 //
00335 //   Coduncts a linear search through the regex array and
00336 //     updates arg result for each regex that matches arg URL
00337 //
00338 template<class Data, class Result> void UrlMatcher<Data, Result>::Match(RequestData * rdata, Result * result)
00339 {
00340   char *url_str;
00341   int *value;
00342   
00343   // Check to see there is any work to before we copy the
00344   //   URL
00345   if (num_el <= 0) {
00346     return;
00347   }
00348 
00349   url_str = rdata->get_string();
00350 
00351   // Can't do a regex match with a NULL string so
00352   //  use an empty one instead
00353   if (url_str == NULL) {
00354     url_str = ats_strdup("");
00355   }
00356 
00357   if (ink_hash_table_lookup(url_ht, url_str, (void **)&value)) { 
00358     Debug("matcher", "%s Matched %s with url at line %d", matcher_name, url_str, data_array[*value].line_num);
00359     data_array[*value].UpdateMatch(result, rdata);
00360   }
00361 
00362   ats_free(url_str);
00363 }
00364 
00365 //
00366 // RegexMatcher<Data,Result>::RegexMatcher()
00367 //
00368 template<class Data, class Result> RegexMatcher<Data, Result>::RegexMatcher(const char *name, const char *filename)
00369   : re_array(NULL),
00370     re_str(NULL),
00371     data_array(NULL),
00372     array_len(-1),
00373     num_el(-1),
00374     matcher_name(name),
00375     file_name(filename)
00376 {
00377 }
00378 
00379 //
00380 // RegexMatcher<Data,Result>::~RegexMatcher()
00381 //
00382 template<class Data, class Result> RegexMatcher<Data, Result>::~RegexMatcher()
00383 {
00384   for (int i = 0; i < num_el; i++) {
00385     pcre_free(re_array[i]);
00386     ats_free(re_str[i]);
00387   }
00388   delete[]re_str;
00389   ats_free(re_array);
00390   delete[]data_array;
00391 }
00392 
00393 //
00394 // void RegexMatcher<Data,Result>::Print()
00395 //
00396 //   Debugging function
00397 //
00398 template<class Data, class Result> void RegexMatcher<Data, Result>::Print()
00399 {
00400   printf("\tRegex Matcher with %d elements\n", num_el);
00401   for (int i = 0; i < num_el; i++) {
00402     printf("\t\tRegex: %s\n", re_str[i]);
00403     data_array[i].Print();
00404   }
00405 }
00406 
00407 //
00408 // void RegexMatcher<Data,Result>::AllocateSpace(int num_entries)
00409 //
00410 template<class Data, class Result> void RegexMatcher<Data, Result>::AllocateSpace(int num_entries)
00411 {
00412   // Should not have been allocated before
00413   ink_assert(array_len == -1);
00414 
00415   re_array = (pcre**)ats_malloc(sizeof(pcre*) * num_entries);
00416   memset(re_array, 0, sizeof(pcre*) * num_entries);
00417 
00418   data_array = new Data[num_entries];
00419 
00420   re_str = new char *[num_entries];
00421   memset(re_str, 0, sizeof(char *) * num_entries);
00422 
00423   array_len = num_entries;
00424   num_el = 0;
00425 }
00426 
00427 //
00428 // char* RegexMatcher<Data,Result>::NewEntry(matcher_line* line_info)
00429 //
00430 template<class Data, class Result> char *RegexMatcher<Data, Result>::NewEntry(matcher_line * line_info)
00431 {
00432   Data *cur_d;
00433   char *errBuf;
00434   char *pattern;
00435   const char *error;
00436   int erroffset;
00437 
00438   // Make sure space has been allocated
00439   ink_assert(num_el >= 0);
00440   ink_assert(array_len >= 0);
00441 
00442   // Make sure we do not overrun the array;
00443   ink_assert(num_el < array_len);
00444 
00445   pattern = line_info->line[1][line_info->dest_entry];
00446   // Make sure that the line_info is not bogus
00447   ink_assert(line_info->dest_entry < MATCHER_MAX_TOKENS);
00448   ink_assert(pattern != NULL);
00449 
00450   // Create the compiled regular expression
00451   re_array[num_el] = pcre_compile(pattern, 0, &error, &erroffset, NULL);
00452   if (!re_array[num_el]) {
00453     errBuf = (char *)ats_malloc(1024 * sizeof(char));
00454     *errBuf = '\0';
00455     snprintf(errBuf, 1024, "%s regular expression error at line %d position %d : %s",
00456                  matcher_name, line_info->line_num, erroffset, error);
00457     re_array[num_el] = NULL;
00458     return errBuf;
00459   }
00460   re_str[num_el] = ats_strdup(pattern);
00461 
00462   // Remove our consumed label from the parsed line
00463   line_info->line[0][line_info->dest_entry] = 0;
00464   line_info->num_el--;
00465 
00466   // Fill in the parameter info
00467   cur_d = data_array + num_el;
00468   errBuf = cur_d->Init(line_info);
00469 
00470   if (errBuf == NULL) {
00471     num_el++;
00472   } else {
00473     // There was a problem so undo the effects this function
00474     ats_free(re_str[num_el]);
00475     re_str[num_el] = NULL;
00476     pcre_free(re_array[num_el]);
00477     re_array[num_el] = NULL;
00478   }
00479 
00480   return errBuf;
00481 }
00482 
00483 //
00484 // void RegexMatcher<Data,Result>::Match(RequestData* rdata, Result* result)
00485 //
00486 //   Coduncts a linear search through the regex array and
00487 //     updates arg result for each regex that matches arg URL
00488 //
00489 template<class Data, class Result> void RegexMatcher<Data, Result>::Match(RequestData * rdata, Result * result)
00490 {
00491   char *url_str;
00492   int r;
00493 
00494   // Check to see there is any work to before we copy the
00495   //   URL
00496   if (num_el <= 0) {
00497     return;
00498   }
00499 
00500   url_str = rdata->get_string();
00501 
00502   // Can't do a regex match with a NULL string so
00503   //  use an empty one instead
00504   if (url_str == NULL) {
00505     url_str = ats_strdup("");
00506   }
00507   // INKqa12980
00508   // The function unescapifyStr() is already called in
00509   // HttpRequestData::get_string(); therefore, no need to call again here.
00510   // unescapifyStr(url_str);
00511 
00512   for (int i = 0; i < num_el; i++) {
00513 
00514     r = pcre_exec(re_array[i], NULL, url_str, strlen(url_str), 0, 0, NULL, 0);
00515     if (r > -1) {
00516       Debug("matcher", "%s Matched %s with regex at line %d", matcher_name, url_str, data_array[i].line_num);
00517       data_array[i].UpdateMatch(result, rdata);
00518     } else if (r < -1) {
00519       // An error has occured
00520       Warning("Error [%d] matching regex at line %d.", r, data_array[i].line_num);
00521     } // else it's -1 which means no match was found.
00522 
00523   }
00524   ats_free(url_str);
00525 }
00526 
00527 //
00528 // HostRegexMatcher<Data,Result>::HostRegexMatcher()
00529 //
00530 template<class Data, class Result>
00531 HostRegexMatcher<Data, Result>::HostRegexMatcher(const char *name, const char *filename)
00532     : RegexMatcher <Data, Result>(name, filename)
00533 {
00534 }
00535 
00536 //
00537 // void HostRegexMatcher<Data,Result>::Match(RequestData* rdata, Result* result)
00538 //
00539 //   Conducts a linear search through the regex array and
00540 //     updates arg result for each regex that matches arg host_regex
00541 //
00542 template<class Data, class Result> void HostRegexMatcher<Data, Result>::Match(RequestData * rdata, Result * result)
00543 {
00544   const char *url_str;
00545   int r;
00546 
00547   // Check to see there is any work to before we copy the
00548   //   URL
00549   if (this->num_el <= 0) {
00550     return;
00551   }
00552 
00553   url_str = rdata->get_host();
00554 
00555   // Can't do a regex match with a NULL string so
00556   //  use an empty one instead
00557   if (url_str == NULL) {
00558     url_str = "";
00559   }
00560   for (int i = 0; i < this->num_el; i++) {
00561     r = pcre_exec(this->re_array[i], NULL, url_str, strlen(url_str), 0, 0, NULL, 0);
00562     if (r != -1) {
00563       Debug("matcher", "%s Matched %s with regex at line %d",
00564             const_cast<char*>(this->matcher_name), url_str, this->data_array[i].line_num);
00565       this->data_array[i].UpdateMatch(result, rdata);
00566     } else {
00567       // An error has occured
00568       Warning("error matching regex at line %d", this->data_array[i].line_num);
00569     }
00570   }
00571 }
00572 
00573 //
00574 // IpMatcher<Data,Result>::IpMatcher()
00575 //
00576 template<class Data, class Result> IpMatcher<Data, Result>::IpMatcher(const char *name, const char *filename)
00577   : data_array(NULL),
00578     array_len(-1),
00579     num_el(-1),
00580     matcher_name(name),
00581     file_name(filename)
00582 {
00583 }
00584 
00585 //
00586 // IpMatcher<Data,Result>::~IpMatcher()
00587 //
00588 template<class Data, class Result> IpMatcher<Data, Result>::~IpMatcher()
00589 {
00590   delete[]data_array;
00591 }
00592 
00593 //
00594 // void IpMatcher<Data,Result>::AllocateSpace(int num_entries)
00595 //
00596 template<class Data, class Result> void IpMatcher<Data, Result>::AllocateSpace(int num_entries)
00597 {
00598   // Should not have been allocated before
00599   ink_assert(array_len == -1);
00600 
00601   data_array = new Data[num_entries];
00602 
00603   array_len = num_entries;
00604   num_el = 0;
00605 }
00606 
00607 //
00608 // char* IpMatcher<Data,Result>::NewEntry(matcher_line* line_info)
00609 //
00610 //    Inserts a range the ip lookup table.
00611 //        Creates new table levels as needed
00612 //
00613 //    Returns NULL is all was OK.  On error returns, a malloc
00614 //     allocated error string which the CALLEE is responsible
00615 //     for deallocating
00616 //
00617 template<class Data, class Result> char *IpMatcher<Data, Result>::NewEntry(matcher_line * line_info)
00618 {
00619 
00620   Data *cur_d;
00621   const char *errPtr;
00622   char *errBuf;
00623   char *match_data;
00624   IpEndpoint addr1, addr2;
00625 
00626   // Make sure space has been allocated
00627   ink_assert(num_el >= 0);
00628   ink_assert(array_len >= 0);
00629 
00630   // Make sure we do not overrun the array;
00631   ink_assert(num_el < array_len);
00632 
00633   match_data = line_info->line[1][line_info->dest_entry];
00634 
00635   // Make sure that the line_info is not bogus
00636   ink_assert(line_info->dest_entry < MATCHER_MAX_TOKENS);
00637   ink_assert(match_data != NULL);
00638 
00639   // Extract the IP range
00640   errPtr = ExtractIpRange(match_data, &addr1.sa, &addr2.sa);
00641   if (errPtr != NULL) {
00642     const size_t errorSize = 1024;
00643     errBuf = (char *)ats_malloc(errorSize * sizeof(char));
00644     snprintf(errBuf, errorSize, "%s %s at %s line %d", matcher_name, errPtr, file_name, line_info->line_num);
00645     return errBuf;
00646   }
00647 
00648   // Remove our consumed label from the parsed line
00649   line_info->line[0][line_info->dest_entry] = NULL;
00650   line_info->num_el--;
00651 
00652   // Fill in the parameter info
00653   cur_d = data_array + num_el;
00654   errBuf = cur_d->Init(line_info);
00655   if (errBuf != NULL) {
00656     return errBuf;
00657   }
00658 
00659   ip_map.mark(&addr1.sa, &addr2.sa, cur_d);
00660 
00661   ++num_el;
00662   return NULL;
00663 }
00664 
00665 //
00666 // void IpMatcherData,Result>::Match(in_addr_t addr, RequestData* rdata, Result* result)
00667 //
00668 template<class Data, class Result>
00669 void IpMatcher<Data, Result>::Match(sockaddr const* addr, RequestData * rdata, Result * result)
00670 {
00671   void* raw;
00672   if (ip_map.contains(addr, &raw)) {
00673     Data *cur = static_cast<Data*>(raw);
00674     ink_assert(cur != 0);
00675     cur->UpdateMatch(result, rdata);
00676   }
00677 }
00678 
00679 
00680 template<class Data, class Result> void IpMatcher<Data, Result>::Print()
00681 {
00682   printf("\tIp Matcher with %d elements, %zu ranges.\n", num_el, ip_map.getCount());
00683   for ( IpMap::iterator spot(ip_map.begin()), limit(ip_map.end()) ; spot != limit ; ++spot) {
00684     char b1[INET6_ADDRSTRLEN], b2[INET6_ADDRSTRLEN];
00685     printf("\tRange %s - %s ",
00686       ats_ip_ntop(spot->min(), b1, sizeof b1),
00687       ats_ip_ntop(spot->max(), b2, sizeof b2)
00688     );
00689     static_cast<Data*>(spot->data())->Print();
00690   }
00691 }
00692 
00693 template<class Data, class Result>
00694 ControlMatcher<Data, Result>::ControlMatcher(const char *file_var, const char *name, const matcher_tags * tags,
00695                                              int flags_in)
00696 {
00697   flags = flags_in;
00698   ink_assert(flags & (ALLOW_HOST_TABLE | ALLOW_REGEX_TABLE | ALLOW_URL_TABLE | ALLOW_IP_TABLE));
00699 
00700   config_tags = tags;
00701   ink_assert(config_tags != NULL);
00702 
00703   matcher_name = name;
00704   config_file_path[0] = '\0';
00705 
00706   if (!(flags & DONT_BUILD_TABLE)) {
00707     ats_scoped_str config_path(RecConfigReadConfigPath(file_var));
00708 
00709     ink_release_assert(config_path);
00710     ink_strlcpy(config_file_path, config_path, sizeof(config_file_path));
00711   }
00712 
00713   reMatch = NULL;
00714   urlMatch = NULL;
00715   hostMatch = NULL;
00716   ipMatch = NULL;
00717   hrMatch = NULL;
00718 
00719   if (!(flags & DONT_BUILD_TABLE)) {
00720     m_numEntries = this->BuildTable();
00721   } else {
00722     m_numEntries = 0;
00723   }
00724 }
00725 
00726 template<class Data, class Result> ControlMatcher<Data, Result>::~ControlMatcher()
00727 {
00728 
00729   delete reMatch;
00730   delete urlMatch;
00731   delete hostMatch;
00732   delete ipMatch;
00733   delete hrMatch;
00734 }
00735 
00736 // void ControlMatcher<Data, Result>::Print()
00737 //
00738 //   Debugging method
00739 //
00740 template<class Data, class Result> void ControlMatcher<Data, Result>::Print()
00741 {
00742   printf("Control Matcher Table: %s\n", matcher_name);
00743   if (hostMatch != NULL) {
00744     hostMatch->Print();
00745   }
00746   if (reMatch != NULL) {
00747     reMatch->Print();
00748   }
00749   if (urlMatch != NULL) {
00750     urlMatch->Print();
00751   }
00752   if (ipMatch != NULL) {
00753     ipMatch->Print();
00754   }
00755   if (hrMatch != NULL) {
00756     hrMatch->Print();
00757   }
00758 }
00759 
00760 
00761 // void ControlMatcher<Data, Result>::Match(RequestData* rdata
00762 //                                          Result* result)
00763 //
00764 //   Queries each table for the Result*
00765 //
00766 template<class Data, class Result> void ControlMatcher<Data, Result>::Match(RequestData * rdata, Result * result)
00767 {
00768   if (hostMatch != NULL) {
00769     hostMatch->Match(rdata, result);
00770   }
00771   if (reMatch != NULL) {
00772     reMatch->Match(rdata, result);
00773   }
00774   if (urlMatch != NULL) {
00775     urlMatch->Match(rdata, result);
00776   }
00777   if (ipMatch != NULL) {
00778     ipMatch->Match(rdata->get_ip(), rdata, result);
00779   }
00780   if (hrMatch != NULL) {
00781     hrMatch->Match(rdata, result);
00782   }
00783 }
00784 
00785 int fstat_wrapper(int fd, struct stat *s);
00786 
00787 // int ControlMatcher::BuildTable() {
00788 //
00789 //    Reads the cache.config file and build the records array
00790 //      from it
00791 //
00792 template<class Data, class Result> int ControlMatcher<Data, Result>::BuildTableFromString(char *file_buf)
00793 {
00794   // Table build locals
00795   Tokenizer bufTok("\n");
00796   tok_iter_state i_state;
00797   const char *tmp;
00798   matcher_line *first = NULL;
00799   matcher_line *current;
00800   matcher_line *last = NULL;
00801   int line_num = 0;
00802   int second_pass = 0;
00803   int numEntries = 0;
00804   bool alarmAlready = false;
00805   char errBuf[1024];
00806   const char *errPtr = NULL;
00807 
00808   // type counts
00809   int hostDomain = 0;
00810   int regex = 0;
00811   int url = 0;
00812   int ip = 0;
00813   int hostregex = 0;
00814 
00815   if (bufTok.Initialize(file_buf, SHARE_TOKS | ALLOW_EMPTY_TOKS) == 0) {
00816     // We have an empty file
00817     return 0;
00818   }
00819   // First get the number of entries
00820   tmp = bufTok.iterFirst(&i_state);
00821   while (tmp != NULL) {
00822 
00823     line_num++;
00824 
00825     // skip all blank spaces at beginning of line
00826     while (*tmp && isspace(*tmp)) {
00827       tmp++;
00828     }
00829 
00830     if (*tmp != '#' && *tmp != '\0') {
00831 
00832       current = (matcher_line *)ats_malloc(sizeof(matcher_line));
00833       errPtr = parseConfigLine((char *) tmp, current, config_tags);
00834 
00835       if (errPtr != NULL) {
00836         if (config_tags != &socks_server_tags) {
00837           snprintf(errBuf, sizeof(errBuf), "%s discarding %s entry at line %d : %s",
00838                    matcher_name, config_file_path, line_num, errPtr);
00839           SignalError(errBuf, alarmAlready);
00840         }
00841         ats_free(current);
00842       } else {
00843 
00844         // Line parsed ok.  Figure out what the destination
00845         //  type is and link it into our list
00846         numEntries++;
00847         current->line_num = line_num;
00848 
00849         switch (current->type) {
00850         case MATCH_HOST:
00851         case MATCH_DOMAIN:
00852           hostDomain++;
00853           break;
00854         case MATCH_IP:
00855           ip++;
00856           break;
00857         case MATCH_REGEX:
00858           regex++;
00859           break;
00860         case MATCH_URL:
00861           url++;
00862           break;
00863         case MATCH_HOST_REGEX:
00864           hostregex++;
00865           break;
00866         case MATCH_NONE:
00867         default:
00868           ink_assert(0);
00869         }
00870 
00871         if (first == NULL) {
00872           ink_assert(last == NULL);
00873           first = last = current;
00874         } else {
00875           last->next = current;
00876           last = current;
00877         }
00878       }
00879     }
00880     tmp = bufTok.iterNext(&i_state);
00881   }
00882 
00883   // Make we have something to do before going on
00884   if (numEntries == 0) {
00885     ats_free(first);
00886     return 0;
00887   }
00888   // Now allocate space for the record pointers
00889   if ((flags & ALLOW_REGEX_TABLE) && regex > 0) {
00890     reMatch = new RegexMatcher<Data, Result> (matcher_name, config_file_path);
00891     reMatch->AllocateSpace(regex);
00892   }
00893 
00894   if ((flags & ALLOW_URL_TABLE) && url > 0) {
00895     urlMatch = new UrlMatcher<Data, Result> (matcher_name, config_file_path);
00896     urlMatch->AllocateSpace(url);
00897   }
00898 
00899   if ((flags & ALLOW_HOST_TABLE) && hostDomain > 0) {
00900     hostMatch = new HostMatcher<Data, Result> (matcher_name, config_file_path);
00901     hostMatch->AllocateSpace(hostDomain);
00902   }
00903 
00904   if ((flags & ALLOW_IP_TABLE) && ip > 0) {
00905     ipMatch = new IpMatcher<Data, Result> (matcher_name, config_file_path);
00906     ipMatch->AllocateSpace(ip);
00907   }
00908 
00909   if ((flags & ALLOW_HOST_REGEX_TABLE) && hostregex > 0) {
00910     hrMatch = new HostRegexMatcher<Data, Result> (matcher_name, config_file_path);
00911     hrMatch->AllocateSpace(hostregex);
00912   }
00913   // Traverse the list and build the records table
00914   current = first;
00915   while (current != NULL) {
00916     second_pass++;
00917     if ((flags & ALLOW_HOST_TABLE) && current->type == MATCH_DOMAIN) {
00918       errPtr = hostMatch->NewEntry(current);
00919     } else if ((flags & ALLOW_HOST_TABLE) && current->type == MATCH_HOST) {
00920       errPtr = hostMatch->NewEntry(current);
00921     } else if ((flags & ALLOW_REGEX_TABLE) && current->type == MATCH_REGEX) {
00922       errPtr = reMatch->NewEntry(current);
00923     } else if ((flags & ALLOW_URL_TABLE) && current->type == MATCH_URL) {
00924       errPtr = urlMatch->NewEntry(current);
00925     } else if ((flags & ALLOW_IP_TABLE) && current->type == MATCH_IP) {
00926       errPtr = ipMatch->NewEntry(current);
00927     } else if ((flags & ALLOW_HOST_REGEX_TABLE) && current->type == MATCH_HOST_REGEX) {
00928       errPtr = hrMatch->NewEntry(current);
00929     } else {
00930       errPtr = NULL;
00931       snprintf(errBuf, sizeof(errBuf), "%s discarding %s entry with unknown type at line %d",
00932                matcher_name, config_file_path, current->line_num);
00933       SignalError(errBuf, alarmAlready);
00934     }
00935 
00936     // Check to see if there was an error in creating
00937     //   the NewEntry
00938     if (errPtr != NULL) {
00939       SignalError(errPtr, alarmAlready);
00940       //ats_free(errPtr); // XXX - why are we trying to free
00941       errPtr = NULL;
00942     }
00943     // Deallocate the parsing structure
00944     last = current;
00945     current = current->next;
00946     ats_free(last);
00947   }
00948 
00949   ink_assert(second_pass == numEntries);
00950 
00951   if (is_debug_tag_set("matcher")) {
00952     Print();
00953   }
00954   return numEntries;
00955 }
00956 
00957 template<class Data, class Result> int ControlMatcher<Data, Result>::BuildTable()
00958 {
00959   // File I/O Locals
00960   char *file_buf;
00961   int ret;
00962 
00963   file_buf = readIntoBuffer(config_file_path, matcher_name, NULL);
00964 
00965   if (file_buf == NULL) {
00966     return 1;
00967   }
00968 
00969   ret = BuildTableFromString(file_buf);
00970   ats_free(file_buf);
00971   return ret;
00972 }
00973 
00974 
00975 /****************************************************************
00976  *    TEMPLATE INSTANTIATIONS GO HERE
00977  *
00978  *  We have to explicitly instantiate the templates so that
00979  *   everything works on with dec ccx, sun CC, and g++
00980  *
00981  *  Details on the different comipilers:
00982  *
00983  *  dec ccx: Does not seem to instantiate anything automatically
00984  *         so it needs all templates manually instantiated
00985  *
00986  *  sun CC: Automatic instantiation works but since we make
00987  *         use of the templates in other files, instantiation
00988  *         only occurs when those files are compiled, breaking
00989  *         the dependency system.  Explict instantiation
00990  *         in this file causes the templates to be reinstantiated
00991  *         when this file changes.
00992  *
00993  *         Also, does not give error messages about template
00994  *           compliation problems.  Requires the -verbose=template
00995  *           flage to error messages
00996  *
00997  *  g++: Requires instantiation to occur in the same file as the
00998  *         the implementation.  Instantiating ControlMatcher
00999  *         automatically instatiatiates the other templates since
01000  *         ControlMatcher makes use of them
01001  *
01002  ****************************************************************/
01003 
01004 template class ControlMatcher<ParentRecord, ParentResult>;
01005 template class HostMatcher<ParentRecord, ParentResult>;
01006 template class RegexMatcher<ParentRecord, ParentResult>;
01007 template class UrlMatcher<ParentRecord, ParentResult>;
01008 template class IpMatcher<ParentRecord, ParentResult>;
01009 template class HostRegexMatcher<ParentRecord, ParentResult>;
01010 
01011 template class ControlMatcher<SplitDNSRecord, SplitDNSResult>;
01012 template class HostMatcher<SplitDNSRecord, SplitDNSResult>;
01013 template class RegexMatcher<SplitDNSRecord, SplitDNSResult>;
01014 template class UrlMatcher<SplitDNSRecord, SplitDNSResult>;
01015 template class IpMatcher<SplitDNSRecord, SplitDNSResult>;
01016 template class HostRegexMatcher<SplitDNSRecord, SplitDNSResult>;
01017 
01018 template class ControlMatcher<CacheControlRecord, CacheControlResult>;
01019 template class HostMatcher<CacheControlRecord, CacheControlResult>;
01020 template class RegexMatcher<CacheControlRecord, CacheControlResult>;
01021 template class UrlMatcher<CacheControlRecord, CacheControlResult>;
01022 template class IpMatcher<CacheControlRecord, CacheControlResult>;
01023 
01024 template class ControlMatcher<CongestionControlRecord, CongestionControlRule>;
01025 template class HostMatcher<CongestionControlRecord, CongestionControlRule>;
01026 template class HostRegexMatcher<CongestionControlRecord, CongestionControlRule>;
01027 template class RegexMatcher<CongestionControlRecord, CongestionControlRule>;
01028 template class UrlMatcher<CongestionControlRecord, CongestionControlRule>;
01029 template class IpMatcher<CongestionControlRecord, CongestionControlRule>;

Generated by  doxygen 1.7.1