/* * This function is only called for redirected requests. It illustrates * several different ways of updating INT64 stats. Some may consider * the particular use of TSDecrementStat() shown below somewhat contrived. */ void update_redirected_method_stats(TSMBuffer bufp, TSMLoc hdr_loc) { const char *txn_method; int length; int64_t tempint; txn_method = TSHttpHdrMethodGet(bufp, hdr_loc, &length); if (NULL != txn_method) { if (0 == strncmp(txn_method, TS_HTTP_METHOD_CONNECT, length)) { TSStatIntIncrement(redirect_count_connect, 1); } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_DELETE, length)) { TSStatIntIncrement(redirect_count_delete, 1); } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_GET, length)) { TSStatIntIncrement(redirect_count_get, 1); } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_HEAD, length)) { TSStatIntIncrement(redirect_count_head, 1); } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_OPTIONS, length)) { // This is a bad idea in a real plugin because it causes a race condition // with other transactions, but is here for illustrative purposes. tempint = TSStatIntGet(redirect_count_options); ++tempint; TSStatIntSet(redirect_count_options, tempint); } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_POST, length)) { // Illustrative only. TSStatIntDecrement(redirect_count_post, 1); TSStatIntIncrement(redirect_count_post, 2); } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_PURGE, length)) { TSStatIntIncrement(redirect_count_purge, 1); } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_PUT, length)) { TSStatIntIncrement(redirect_count_put, 1); } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_TRACE, length)) { TSStatIntIncrement(redirect_count_trace, 1); } else { TSStatIntIncrement(redirect_count_unknown, 1); } } }
static void stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, TSMutex create_mutex) { int stat_id = -1; ENTRY search, *result = NULL; static __thread struct hsearch_data stat_cache; static __thread bool hash_init = false; if (unlikely(!hash_init)) { hcreate_r(TS_MAX_API_STATS << 1, &stat_cache); hash_init = true; TSDebug(DEBUG_TAG, "stat cache hash init"); } search.key = name; search.data = 0; hsearch_r(search, FIND, &result, &stat_cache); if (unlikely(result == NULL)) { // This is an unlikely path because we most likely have the stat cached // so this mutex won't be much overhead and it fixes a race condition // in the RecCore. Hopefully this can be removed in the future. TSMutexLock(create_mutex); if (TS_ERROR == TSStatFindName((const char *)name, &stat_id)) { stat_id = TSStatCreate((const char *)name, TS_RECORDDATATYPE_INT, persist_type, TS_STAT_SYNC_SUM); if (stat_id == TS_ERROR) { TSDebug(DEBUG_TAG, "Error creating stat_name: %s", name); } else { TSDebug(DEBUG_TAG, "Created stat_name: %s stat_id: %d", name, stat_id); } } TSMutexUnlock(create_mutex); if (stat_id >= 0) { search.key = TSstrdup(name); search.data = (void *)((intptr_t)stat_id); hsearch_r(search, ENTER, &result, &stat_cache); TSDebug(DEBUG_TAG, "Cached stat_name: %s stat_id: %d", name, stat_id); } } else { stat_id = (int)((intptr_t)result->data); } if (likely(stat_id >= 0)) { TSStatIntIncrement(stat_id, amount); } else { TSDebug(DEBUG_TAG, "stat error! stat_name: %s stat_id: %d", name, stat_id); } }
static void handle_client_lookup(TSHttpTxn txnp, TSCont contp) { TSMBuffer bufp; TSMLoc hdr_loc, url_loc; int host_length; in_addr_t clientip = 0; const char *host; if (TSIsDebugTagSet("redirect")) { struct sockaddr const *addr = TSHttpTxnClientAddrGet(txnp); if (addr) { socklen_t addr_size = 0; if (addr->sa_family == AF_INET) { addr_size = sizeof(struct sockaddr_in); } else if (addr->sa_family == AF_INET6) { addr_size = sizeof(struct sockaddr_in6); } if (addr_size > 0) { char clientstring[INET6_ADDRSTRLEN]; if (NULL != inet_ntop(addr->sa_family, addr, clientstring, addr_size)) { TSDebug(PLUGIN_NAME, "clientip is %s and block_ip is %s", clientstring, block_ip); } } } } if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve client request header", PLUGIN_NAME); goto done; } if (TSHttpHdrUrlGet(bufp, hdr_loc, &url_loc) != TS_SUCCESS) { TSError("[%s] Couldn't retrieve request url", PLUGIN_NAME); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } host = TSUrlHostGet(bufp, url_loc, &host_length); if (!host) { TSError("[%s] Couldn't retrieve request hostname", PLUGIN_NAME); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } /* * Check to see if the client is already headed to the redirect site. */ if (strncmp(host, url_redirect, host_length) == 0) { TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); goto done; } /* TODO: This is odd, clientip is never set ... */ if (ip_deny == clientip) { TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp); update_redirected_method_stats(bufp, hdr_loc); TSHandleMLocRelease(bufp, hdr_loc, url_loc); TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc); /* * Increment the local redirect stat and do global update: */ TSStatIntIncrement(requests_redirects, 1); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR); return; } done: // Increment the local number unchanged stat and do global update: TSStatIntIncrement(requests_unchanged, 1); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); }