Repository: trafficserver Updated Branches: refs/heads/master d9e3d462b -> 67a95c776
[TS-2683]: Additional config enhancements per Leif's suggestions Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/67a95c77 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/67a95c77 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/67a95c77 Branch: refs/heads/master Commit: 67a95c776ea291b5950f7caa78829c1771df6085 Parents: d9e3d46 Author: Sudheer Vinukonda <[email protected]> Authored: Fri Oct 31 20:48:28 2014 +0000 Committer: Sudheer Vinukonda <[email protected]> Committed: Fri Oct 31 20:48:28 2014 +0000 ---------------------------------------------------------------------- .../background_fetch/background_fetch.cc | 233 ++++++++++--------- 1 file changed, 119 insertions(+), 114 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/67a95c77/plugins/experimental/background_fetch/background_fetch.cc ---------------------------------------------------------------------- diff --git a/plugins/experimental/background_fetch/background_fetch.cc b/plugins/experimental/background_fetch/background_fetch.cc index 732e0d1..fa8be35 100644 --- a/plugins/experimental/background_fetch/background_fetch.cc +++ b/plugins/experimental/background_fetch/background_fetch.cc @@ -48,26 +48,25 @@ // Constants const char PLUGIN_NAME[] = "background_fetch"; -static int g_background_fetch_ArgIndex = 0; // Types -typedef std::set<std::string> stringSet; - typedef struct { - stringSet contentTypeSet; - stringSet userAgentSet; - stringSet clientIpSet; -} ExclusionSet; + bool exclude; + std::string ruleField; + std::string ruleValue; +} BgFetchRuleStruct; + +typedef std::map<uint32_t, BgFetchRuleStruct> BgFetchRuleMap; // Global config, if we don't have a remap specific config. -static ExclusionSet gExclusionSet; +static BgFetchRuleMap gBgFetchRuleMap; /////////////////////////////////////////////////////////////////////////// // Read a config file // static bool -read_config(char* config_file, ExclusionSet* ri) +read_config(char* config_file, BgFetchRuleMap* ri) { char file_path[1024]; TSFile file; @@ -90,10 +89,9 @@ read_config(char* config_file, ExclusionSet* ri) } } - stringSet* contentTypeSetP = &(ri->contentTypeSet); - stringSet* userAgentSetP = &(ri->userAgentSet); - stringSet* clientIpSetP = &(ri->clientIpSet); + BgFetchRuleMap* bgFetchRuleMapP = ri; char buffer[8192]; + uint32_t index = 0; memset(buffer, 0, sizeof(buffer)); while (TSfgets(file, buffer, sizeof(buffer) - 1) != NULL) { @@ -114,27 +112,30 @@ read_config(char* config_file, ExclusionSet* ri) char* cfg = strtok_r(buffer, "\n\r\n", &savePtr); if (cfg != NULL) { + TSDebug(PLUGIN_NAME, "setting background_fetch exclusion criterion based on string: %s", cfg); char* cfg_type = strtok_r(buffer, " ", &savePtr); + char* cfg_name = NULL; char* cfg_value = NULL; - - TSDebug(PLUGIN_NAME, "setting background_fetch exclusion criterion based on string: %s", cfg); + bool exclude = false; if (cfg_type) { - cfg_value = strtok_r(NULL, " ", &savePtr); - } - - if (cfg_type && cfg_value) { - if (!strcmp(cfg_type, "Content-Type")) { - TSDebug(PLUGIN_NAME, "adding content-type %s", cfg_value); - contentTypeSetP->insert(cfg_value); - } else if (!strcmp(cfg_type, "User-Agent")) { - TSDebug(PLUGIN_NAME, "adding user-agent %s", cfg_value); - userAgentSetP->insert(cfg_value); - } else if (!strcmp(cfg_type, "Client-IP")) { - TSDebug(PLUGIN_NAME, "adding client-ip %s", cfg_value); - clientIpSetP->insert(cfg_value); - } else { - TSError("%s: Unknown config type: %s", PLUGIN_NAME, cfg_type); + if (!strcmp(cfg_type, "exclude")) { + exclude = true; + } else if (strcmp(cfg_type, "include")) { + TSError("%s: invalid specifier %s, skipping config line", PLUGIN_NAME, cfg_type); + memset(buffer, 0, sizeof(buffer)); + continue; + } + cfg_name = strtok_r(NULL, " ", &savePtr); + if (cfg_name) { + cfg_value = strtok_r(NULL, " ", &savePtr); + if (cfg_value) { + TSDebug(PLUGIN_NAME, "adding background_fetch exclusion rule %d for %s:%s", exclude, cfg_name, cfg_value); + BgFetchRuleStruct ruleS = {exclude, cfg_name, cfg_value}; + bgFetchRuleMapP->insert(std::make_pair(index++, ruleS)); + } else { + TSError("%s: invalid value %s, skipping config line", PLUGIN_NAME, cfg_name); + } } } memset(buffer, 0, sizeof(buffer)); @@ -644,50 +645,91 @@ cont_check_cacheable(TSCont contp, TSEvent /* event ATS_UNUSED */, void* edata) return 0; } +/////////////////////////////////////////////////////////////////////////// +// Check if a header excludes us from running the background fetch +// +static bool +check_client_ip_configured(TSHttpTxn txnp, const char* cfg_ip) +{ + const sockaddr* client_ip = TSHttpTxnClientAddrGet(txnp); + char ip_buf[INET6_ADDRSTRLEN]; + + if(AF_INET == client_ip->sa_family) { + inet_ntop(AF_INET, &(reinterpret_cast<const sockaddr_in*>(client_ip)->sin_addr), ip_buf, INET_ADDRSTRLEN); + } else if(AF_INET6 == client_ip->sa_family) { + inet_ntop(AF_INET6, &(reinterpret_cast<const sockaddr_in6*>(client_ip)->sin6_addr), ip_buf, INET6_ADDRSTRLEN); + } else { + TSError("%s: unknown family %d", PLUGIN_NAME, client_ip->sa_family); + return false; + } + + TSDebug(PLUGIN_NAME,"cfg_ip %s, client_ip %s", cfg_ip,ip_buf); + + if ((strlen(cfg_ip) == strlen(ip_buf)) && !strcmp(cfg_ip, ip_buf)) { + TSDebug(PLUGIN_NAME,"bg fetch for ip %s, configured ip %s", ip_buf, cfg_ip); + return true; + } + + return false; +} + /////////////////////////////////////////////////////////////////////////// // Check if a header excludes us from running the background fetch // static bool -check_hdr_configured(TSMBuffer hdr_bufp, TSMLoc req_hdrs, const char* field_type, int field_len, stringSet* cfg_set) +check_field_configured(TSHttpTxn txnp, const char* field_name, const char* cfg_val) { + // check for client-ip first + if (!strcmp(field_name, "Client-IP")) { + if (check_client_ip_configured(txnp, cfg_val)) { + TSDebug(PLUGIN_NAME, "Found client_ip match"); + return true; + } + } + bool hdr_found = false; - TSMLoc loc = TSMimeHdrFieldFind(hdr_bufp, req_hdrs, field_type, field_len); + TSMBuffer hdr_bufp; + TSMLoc req_hdrs; + + TSReturnCode ret = TSHttpTxnClientReqGet(txnp, &hdr_bufp, &req_hdrs); + + if (ret != TS_SUCCESS) { + // something wrong.. + TSError ("%s: Failed to get req headers", PLUGIN_NAME); + return false; + } + + TSMLoc loc = TSMimeHdrFieldFind(hdr_bufp, req_hdrs, field_name, -1); if (TS_NULL_MLOC != loc) { int val_len = 0; const char *val_str = TSMimeHdrFieldValueStringGet(hdr_bufp, req_hdrs, loc, 0, &val_len); if (!val_str || val_len <= 0) { - TSDebug(PLUGIN_NAME,"invalid content type"); + TSDebug(PLUGIN_NAME,"invalid field"); } else { - stringSet::iterator it = cfg_set->begin(); - - while(it!=cfg_set->end()) { - TSDebug(PLUGIN_NAME, "comparing with %s", (*it).c_str()); - if (NULL != strstr(val_str, (*it).c_str())) { - TSDebug(PLUGIN_NAME,"excluding bg fetch for configured field %s", (*it).c_str()); - hdr_found = true; - break; - } - it++; + TSDebug(PLUGIN_NAME, "comparing with %s", cfg_val); + if (NULL != strstr(val_str, cfg_val)) { + hdr_found = true; } - TSHandleMLocRelease(hdr_bufp, req_hdrs, loc); } + TSHandleMLocRelease(hdr_bufp, req_hdrs, loc); } else { - TSDebug(PLUGIN_NAME, "no field %s in request header", field_type); + TSDebug(PLUGIN_NAME, "no field %s in request header", field_name); } + + TSHandleMLocRelease(hdr_bufp, TS_NULL_MLOC, req_hdrs); return hdr_found; } - /////////////////////////////////////////////////////////////////////////// // Check the configuration (either per remap, or global), and decide if // this request is allowed to trigger a background fetch. // static bool -is_background_fetch_allowed(TSHttpTxn txnp, ExclusionSet* ri) +is_background_fetch_allowed(TSHttpTxn txnp, BgFetchRuleMap* ri) { TSDebug(PLUGIN_NAME, "Testing: request is internal?"); if (TSHttpIsInternalRequest(txnp) == TS_SUCCESS) { @@ -696,59 +738,16 @@ is_background_fetch_allowed(TSHttpTxn txnp, ExclusionSet* ri) bool allow_bg_fetch = true; - stringSet* contentTypeSetP = &(ri->contentTypeSet); - stringSet* userAgentSetP = &(ri->userAgentSet); - stringSet* clientIpSetP = &(ri->clientIpSet); - - const sockaddr* client_ip = TSHttpTxnClientAddrGet(txnp); - char ip_buf[INET6_ADDRSTRLEN]; - - if(AF_INET == client_ip->sa_family) { - inet_ntop(AF_INET, &(reinterpret_cast<const sockaddr_in*>(client_ip)->sin_addr), ip_buf, INET_ADDRSTRLEN); - } else if(AF_INET6 == client_ip->sa_family) { - inet_ntop(AF_INET6, &(reinterpret_cast<const sockaddr_in6*>(client_ip)->sin6_addr), ip_buf, INET6_ADDRSTRLEN); - } else { - TSError("%s: unknown family %d", PLUGIN_NAME, client_ip->sa_family); - } - - TSDebug(PLUGIN_NAME,"client_ip %s", ip_buf); - - for (stringSet::iterator it=clientIpSetP->begin(); it != clientIpSetP->end(); ++it) { - const char* cfg_ip = (*it).c_str(); - - if ((strlen(cfg_ip) == strlen(ip_buf)) && !strcmp(cfg_ip, ip_buf)) { - TSDebug(PLUGIN_NAME,"excluding bg fetch for ip %s, configured ip %s", ip_buf, cfg_ip); - allow_bg_fetch = false; - break; - } - } - - if (!allow_bg_fetch) { - return false; - } - - TSMBuffer hdr_bufp; - TSMLoc req_hdrs; - - if (TSHttpTxnClientReqGet(txnp, &hdr_bufp, &req_hdrs) == TS_SUCCESS) { - if (check_hdr_configured (hdr_bufp, req_hdrs, TS_MIME_FIELD_CONTENT_TYPE, TS_MIME_LEN_CONTENT_TYPE, contentTypeSetP)) { - TSDebug(PLUGIN_NAME, "found content-type match"); - allow_bg_fetch = false; - goto done; - } - if (check_hdr_configured (hdr_bufp, req_hdrs, TS_MIME_FIELD_USER_AGENT, TS_MIME_LEN_USER_AGENT, userAgentSetP)) { - TSDebug(PLUGIN_NAME, "found user-agent match"); - allow_bg_fetch = false; - goto done; + for (BgFetchRuleMap::iterator it=ri->begin(); it!=ri->end(); ++it) { + BgFetchRuleStruct sRule = it->second; + const char* ruleField = sRule.ruleField.c_str(); + if (check_field_configured (txnp, ruleField, sRule.ruleValue.c_str())) { + TSDebug(PLUGIN_NAME, "found field match %s, exclude %d", ruleField, sRule.exclude); + allow_bg_fetch = !sRule.exclude; + break; } - } else { - // something wrong.. - TSError ("%s: Failed to get req headers", PLUGIN_NAME); - return false; } - done: - TSHandleMLocRelease(hdr_bufp, TS_NULL_MLOC, req_hdrs); return allow_bg_fetch; } @@ -765,14 +764,16 @@ is_background_fetch_allowed(TSHttpTxn txnp, ExclusionSet* ri) // there could be other plugins that modifies the response after us. // static int -cont_handle_response(TSCont /* contp ATS_UNUSED */, TSEvent /* event ATS_UNUSED */, void* edata) +cont_handle_response(TSCont contp, TSEvent /* event ATS_UNUSED */, void* edata) { // ToDo: If we want to support per-remap configurations, we have to pass along the data here TSHttpTxn txnp = static_cast<TSHttpTxn>(edata); - ExclusionSet *ri = static_cast<ExclusionSet *> (TSHttpTxnArgGet(txnp, g_background_fetch_ArgIndex)); + BgFetchRuleMap *ri = static_cast<BgFetchRuleMap*>(TSContDataGet(contp)); if (ri == NULL) { - ri = &gExclusionSet; + // something wrong.. + TSError("%s: can't get BgFetchRule Map", PLUGIN_NAME); + ri = &gBgFetchRuleMap; } if (is_background_fetch_allowed(txnp, ri)) { @@ -810,7 +811,7 @@ TSPluginInit(int argc, const char* argv[]) TSPluginRegistrationInfo info; static const struct option longopt[] = { { const_cast<char *>("log"), required_argument, NULL, 'l' }, - { const_cast<char *>("exclude"), required_argument, NULL, 'e' }, + { const_cast<char *>("config"), required_argument, NULL, 'c' }, { NULL, no_argument, NULL, '\0' } }; @@ -822,25 +823,19 @@ TSPluginInit(int argc, const char* argv[]) TSError("%s: plugin registration failed.\n", PLUGIN_NAME); } - if (TSHttpArgIndexReserve("background_fetch", "exclustion criteria index", &g_background_fetch_ArgIndex) != TS_SUCCESS) { - TSError("%s: Failed to reserve an argument index", PLUGIN_NAME); - TSAssert(0); - return; - } - gConfig = new BGFetchConfig(); optind = 1; while (true) { - int opt = getopt_long(argc, (char* const *)argv, "le", longopt, NULL); + int opt = getopt_long(argc, (char* const *)argv, "lc", longopt, NULL); switch (opt) { case 'l': gConfig->create_log(optarg); break; - case 'e': + case 'c': TSDebug(PLUGIN_NAME, "config file %s..", optarg); - read_config(optarg, &gExclusionSet); + read_config(optarg, &gBgFetchRuleMap); break; } @@ -850,7 +845,10 @@ TSPluginInit(int argc, const char* argv[]) } TSDebug(PLUGIN_NAME, "Initialized"); - TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, TSContCreate(cont_handle_response, NULL)); + + TSCont cont = TSContCreate(cont_handle_response, NULL); + TSContDataSet(cont, static_cast<void*>(&gBgFetchRuleMap)); + TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, cont); } @@ -885,11 +883,16 @@ TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size) TSReturnCode TSRemapNewInstance(int argc, char* argv[], void** ih, char* /* errbuf */, int /* errbuf_size */) { - ExclusionSet *ri = new ExclusionSet(); + BgFetchRuleMap *ri = new BgFetchRuleMap(); if (ri == NULL) { TSError("%s:Unable to create remap instance", PLUGIN_NAME); return TS_ERROR; } + + if (gConfig == NULL) { + TSDebug(PLUGIN_NAME, "creating gConfig"); + gConfig = new BGFetchConfig(); + } char* fileName = NULL; if (argc > 2) { @@ -907,7 +910,7 @@ TSRemapNewInstance(int argc, char* argv[], void** ih, char* /* errbuf */, int / void TSRemapDeleteInstance(void* ih) { - ExclusionSet* ri = static_cast<ExclusionSet*>(ih); + BgFetchRuleMap* ri = static_cast<BgFetchRuleMap*>(ih); delete ri; } @@ -923,8 +926,10 @@ TSRemapDoRemap(void* ih, TSHttpTxn txnp, TSRemapRequestInfo* /* rri */) } TSDebug(PLUGIN_NAME, "background fetch TSRemapDoRemap..."); - TSHttpTxnArgSet(txnp, g_background_fetch_ArgIndex, static_cast<void *> (ih)); - TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, TSContCreate(cont_handle_response, NULL)); + + TSCont cont = TSContCreate(cont_handle_response, NULL); + TSContDataSet(cont, static_cast<void*>(ih)); + TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, cont); return TSREMAP_NO_REMAP; }
