| /** @file |
| |
| A brief file description |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /***************************************************************************** |
| * Filename: InkMgmtAPI.cc |
| * Purpose: This file implements all traffic server management functions. |
| * Created: 9/11/00 |
| * Created by: Lan Tran |
| * |
| * |
| ***************************************************************************/ |
| #include "libts.h" |
| #include <limits.h> |
| #include "I_Layout.h" |
| |
| #include "mgmtapi.h" |
| #include "CfgContextManager.h" |
| #include "CfgContextImpl.h" |
| #include "CfgContextUtils.h" |
| #include "CoreAPI.h" |
| #include "CoreAPIShared.h" |
| |
| #include "TextBuffer.h" |
| |
| // forward declarations |
| void init_pdss_format(TSPdSsFormat * info); |
| |
| |
| /*************************************************************************** |
| * API Memory Management |
| ***************************************************************************/ |
| void * |
| _TSmalloc(unsigned int size, const char * /* path ATS_UNUSED */ ) |
| { |
| return ats_malloc(size); |
| } |
| |
| void * |
| _TSrealloc(void *ptr, unsigned int size, const char * /* path ATS_UNUSED */) |
| { |
| return ats_realloc(ptr, size); |
| } |
| |
| char * |
| _TSstrdup(const char *str, int length, const char * /* path ATS_UNUSED */) |
| { |
| return ats_strndup(str, length); |
| } |
| |
| void |
| _TSfree(void *ptr) |
| { |
| ats_free(ptr); |
| } |
| |
| |
| /*************************************************************************** |
| * API Helper Functions for Data Carrier Structures |
| ***************************************************************************/ |
| |
| /*--- TSList operations -------------------------------------------------*/ |
| tsapi TSList |
| TSListCreate(void) |
| { |
| return (void *) create_queue(); |
| } |
| |
| /* NOTE: The List must be EMPTY */ |
| tsapi void |
| TSListDestroy(TSList l) |
| { |
| if (!l) |
| return; |
| |
| delete_queue((LLQ *) l); |
| return; |
| } |
| |
| tsapi TSError |
| TSListEnqueue(TSList l, void *data) |
| { |
| int ret; |
| |
| ink_assert(l && data); |
| if (!l || !data) |
| return TS_ERR_PARAMS; |
| |
| ret = enqueue((LLQ *) l, data); /* returns TRUE=1 or FALSE=0 */ |
| if (ret == 0) { |
| return TS_ERR_FAIL; |
| } else { |
| return TS_ERR_OKAY; |
| } |
| } |
| |
| tsapi void * |
| TSListDequeue(TSList l) |
| { |
| ink_assert(l); |
| if (!l || queue_is_empty((LLQ *) l)) |
| return NULL; |
| |
| return dequeue((LLQ *) l); |
| } |
| |
| tsapi bool |
| TSListIsEmpty(TSList l) |
| { |
| int ret; |
| |
| ink_assert(l); |
| if (!l) |
| return true; // list doesn't exist, so it's empty |
| |
| ret = queue_is_empty((LLQ *) l); /* returns 0 if empty, non-zero if not empty */ |
| if (ret == 0) { /* empty */ |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| tsapi int |
| TSListLen(TSList l) |
| { |
| ink_assert(l); |
| if (!l) |
| return -1; |
| |
| return queue_len((LLQ *) l); |
| } |
| |
| tsapi bool |
| TSListIsValid(TSList l) |
| { |
| int i, len; |
| void *ele; |
| |
| if (!l) |
| return false; |
| |
| len = queue_len((LLQ *) l); |
| for (i = 0; i < len; i++) { |
| ele = (void *) dequeue((LLQ *) l); |
| if (!ele) |
| return false; |
| enqueue((LLQ *) l, ele); |
| } |
| return true; |
| } |
| |
| /*--- TSIpAddrList operations -------------------------------------------------*/ |
| tsapi TSIpAddrList |
| TSIpAddrListCreate(void) |
| { |
| return (void *) create_queue(); /* this queue will be a list of IpAddrEle* */ |
| } |
| |
| tsapi void |
| TSIpAddrListDestroy(TSIpAddrList ip_addrl) |
| { |
| TSIpAddrEle *ipaddr_ele; |
| |
| if (!ip_addrl) { |
| return; |
| } |
| |
| /* dequeue each element and free it; |
| currently, an element can only be an TSIpAddrEle |
| or it can be an TSIpAddr ?? */ |
| while (!queue_is_empty((LLQ *) ip_addrl)) { |
| ipaddr_ele = (TSIpAddrEle *) dequeue((LLQ *) ip_addrl); |
| |
| if (!ipaddr_ele) |
| continue; |
| |
| TSIpAddrEleDestroy(ipaddr_ele); |
| } |
| |
| /* we have removed everything on the list so free list */ |
| delete_queue((LLQ *) ip_addrl); |
| return; |
| } |
| |
| tsapi TSError |
| TSIpAddrListEnqueue(TSIpAddrList ip_addrl, TSIpAddrEle * ip_addr) |
| { |
| int ret; |
| |
| ink_assert(ip_addrl && ip_addr); |
| if (!ip_addrl || !ip_addr) |
| return TS_ERR_PARAMS; |
| |
| ret = enqueue((LLQ *) ip_addrl, ip_addr); |
| if (ret == 0) { |
| return TS_ERR_FAIL; |
| } else { |
| return TS_ERR_OKAY; |
| } |
| } |
| |
| |
| /* The the TSIpAddrEle returned is actually removed from the end of list */ |
| tsapi TSIpAddrEle * |
| TSIpAddrListDequeue(TSIpAddrList ip_addrl) |
| { |
| ink_assert(ip_addrl); |
| if (!ip_addrl || queue_is_empty((LLQ *) ip_addrl)) |
| return NULL; |
| |
| return (TSIpAddrEle *) dequeue((LLQ *) ip_addrl); |
| } |
| |
| |
| tsapi int |
| TSIpAddrListLen(TSIpAddrList ip_addrl) |
| { |
| ink_assert(ip_addrl); |
| if (!ip_addrl) |
| return -1; |
| |
| return queue_len((LLQ *) ip_addrl); |
| } |
| |
| tsapi bool |
| TSIpAddrListIsEmpty(TSIpAddrList ip_addrl) |
| { |
| ink_assert(ip_addrl); |
| if (!ip_addrl) |
| return true; |
| |
| return queue_is_empty((LLQ *) ip_addrl); |
| } |
| |
| // returns false if any of the IpAddrEle is not an valid IP address by making |
| // use of ccu_checkIpAddrEle; if return false, the ip's may be reordered |
| // from the original list |
| tsapi bool |
| TSIpAddrListIsValid(TSIpAddrList ip_addrl) |
| { |
| int i, len; |
| TSIpAddrEle *ele; |
| |
| if (!ip_addrl) |
| return false; |
| |
| len = queue_len((LLQ *) ip_addrl); |
| for (i = 0; i < len; i++) { |
| ele = (TSIpAddrEle *) dequeue((LLQ *) ip_addrl); |
| if (!ccu_checkIpAddrEle(ele)) { |
| enqueue((LLQ *) ip_addrl, ele); |
| return false; |
| } |
| enqueue((LLQ *) ip_addrl, ele); |
| } |
| return true; |
| } |
| |
| /*--- TSPortList operations ----------------------------------------------*/ |
| tsapi TSPortList |
| TSPortListCreate() |
| { |
| return (void *) create_queue(); /* this queue will be a list of TSPortEle* */ |
| } |
| |
| tsapi void |
| TSPortListDestroy(TSPortList portl) |
| { |
| TSPortEle *port_ele; |
| |
| if (!portl) { |
| return; |
| } |
| // dequeue each element and free it |
| while (!queue_is_empty((LLQ *) portl)) { |
| port_ele = (TSPortEle *) dequeue((LLQ *) portl); |
| |
| if (!port_ele) |
| continue; |
| |
| TSPortEleDestroy(port_ele); |
| } |
| |
| /* we have removed everything on the list so free list */ |
| delete_queue((LLQ *) portl); |
| return; |
| } |
| |
| tsapi TSError |
| TSPortListEnqueue(TSPortList portl, TSPortEle * port) |
| { |
| int ret; |
| |
| ink_assert(portl && port); |
| if (!portl || !port) |
| return TS_ERR_PARAMS; |
| |
| ret = enqueue((LLQ *) portl, port); /* returns TRUE=1 or FALSE=0 */ |
| if (ret == 0) { |
| return TS_ERR_FAIL; |
| } else { |
| return TS_ERR_OKAY; |
| } |
| } |
| |
| tsapi TSPortEle * |
| TSPortListDequeue(TSPortList portl) |
| { |
| ink_assert(portl); |
| if (!portl || queue_is_empty((LLQ *) portl)) |
| return NULL; |
| |
| return (TSPortEle *) dequeue((LLQ *) portl); |
| } |
| |
| tsapi int |
| TSPortListLen(TSPortList portl) |
| { |
| ink_assert(portl); |
| if (!portl) |
| return -1; |
| |
| return queue_len((LLQ *) portl); |
| } |
| |
| tsapi bool |
| TSPortListIsEmpty(TSPortList portl) |
| { |
| ink_assert(portl); |
| if (!portl) |
| return true; |
| |
| return queue_is_empty((LLQ *) portl); |
| } |
| |
| // returns false if any of the PortEle's has a port_a <= 0; |
| // if returns false, then will return the entire port list |
| // intact, although the ports may not be ordered in the same way |
| tsapi bool |
| TSPortListIsValid(TSPortList portl) |
| { |
| int i, len; |
| TSPortEle *ele; |
| |
| if (!portl) |
| return false; |
| |
| len = queue_len((LLQ *) portl); |
| for (i = 0; i < len; i++) { |
| ele = (TSPortEle *) dequeue((LLQ *) portl); |
| if (!ccu_checkPortEle(ele)) { |
| enqueue((LLQ *) portl, ele); |
| return false; |
| } |
| enqueue((LLQ *) portl, ele); |
| } |
| return true; |
| } |
| |
| |
| /*--- TSDomainList operations -----------------------------------------*/ |
| tsapi TSDomainList |
| TSDomainListCreate() |
| { |
| return (void *) create_queue(); /* this queue will be a list of char* */ |
| } |
| |
| tsapi void |
| TSDomainListDestroy(TSDomainList domainl) |
| { |
| TSDomain *domain; |
| |
| if (!domainl) { |
| return; |
| } |
| |
| /* dequeue each element and free it */ |
| while (!queue_is_empty((LLQ *) domainl)) { |
| domain = (TSDomain *) dequeue((LLQ *) domainl); |
| |
| if (!domain) |
| continue; |
| |
| TSDomainDestroy(domain); |
| } |
| |
| delete_queue((LLQ *) domainl); |
| } |
| |
| tsapi TSError |
| TSDomainListEnqueue(TSDomainList domainl, TSDomain * domain) |
| { |
| int ret; |
| |
| ink_assert(domainl && domain); |
| if (!domainl || !domain) |
| return TS_ERR_PARAMS; |
| |
| ret = enqueue((LLQ *) domainl, domain); /* returns TRUE=1 or FALSE=0 */ |
| if (ret == 0) { |
| return TS_ERR_FAIL; |
| } else { |
| return TS_ERR_OKAY; |
| } |
| } |
| |
| tsapi TSDomain * |
| TSDomainListDequeue(TSDomainList domainl) |
| { |
| ink_assert(domainl); |
| if (!domainl || queue_is_empty((LLQ *) domainl)) |
| return NULL; |
| |
| return (TSDomain *) dequeue((LLQ *) domainl); |
| } |
| |
| tsapi bool |
| TSDomainListIsEmpty(TSDomainList domainl) |
| { |
| ink_assert(domainl); |
| if (!domainl) |
| return true; |
| |
| return queue_is_empty((LLQ *) domainl); |
| } |
| |
| tsapi int |
| TSDomainListLen(TSDomainList domainl) |
| { |
| ink_assert(domainl); |
| if (!domainl) |
| return -1; |
| |
| return queue_len((LLQ *) domainl); |
| } |
| |
| // returns false if encounter a NULL hostname and ip |
| tsapi bool |
| TSDomainListIsValid(TSDomainList domainl) |
| { |
| int i, len; |
| TSDomain *dom; |
| |
| if (!domainl) |
| return false; |
| |
| len = queue_len((LLQ *) domainl); |
| for (i = 0; i < len; i++) { |
| dom = (TSDomain *) dequeue((LLQ *) domainl); |
| if (!dom) { |
| return false; |
| } |
| if (!dom->domain_val) { |
| return false; |
| } |
| enqueue((LLQ *) domainl, dom); |
| } |
| return true; |
| |
| } |
| |
| /*--- TSStringList operations --------------------------------------*/ |
| tsapi TSStringList |
| TSStringListCreate() |
| { |
| return (void *) create_queue(); /* this queue will be a list of char* */ |
| } |
| |
| /* usually, must be an empty list before destroying*/ |
| tsapi void |
| TSStringListDestroy(TSStringList strl) |
| { |
| char *str; |
| |
| if (!strl) { |
| return; |
| } |
| |
| /* dequeue each element and free it */ |
| while (!queue_is_empty((LLQ *) strl)) { |
| str = (char *) dequeue((LLQ *) strl); |
| ats_free(str); |
| } |
| |
| delete_queue((LLQ *) strl); |
| } |
| |
| tsapi TSError |
| TSStringListEnqueue(TSStringList strl, char *str) |
| { |
| int ret; |
| |
| ink_assert(strl && str); |
| if (!strl || !str) |
| return TS_ERR_PARAMS; |
| |
| ret = enqueue((LLQ *) strl, str); /* returns TRUE=1 or FALSE=0 */ |
| if (ret == 0) { |
| return TS_ERR_FAIL; |
| } else { |
| return TS_ERR_OKAY; |
| } |
| } |
| |
| tsapi char * |
| TSStringListDequeue(TSStringList strl) |
| { |
| ink_assert(strl); |
| if (!strl || queue_is_empty((LLQ *) strl)) |
| return NULL; |
| |
| return (char *) dequeue((LLQ *) strl); |
| } |
| |
| tsapi bool |
| TSStringListIsEmpty(TSStringList strl) |
| { |
| ink_assert(strl); |
| if (!strl) |
| return true; |
| |
| return queue_is_empty((LLQ *) strl); |
| } |
| |
| tsapi int |
| TSStringListLen(TSStringList strl) |
| { |
| ink_assert(strl); |
| if (!strl) |
| return -1; |
| |
| return queue_len((LLQ *) strl); |
| } |
| |
| // returns false if any element is NULL string |
| tsapi bool |
| TSStringListIsValid(TSStringList strl) |
| { |
| int i, len; |
| char *str; |
| |
| if (!strl) |
| return false; |
| |
| len = queue_len((LLQ *) strl); |
| for (i = 0; i < len; i++) { |
| str = (char *) dequeue((LLQ *) strl); |
| if (!str) |
| return false; |
| enqueue((LLQ *) strl, str); |
| } |
| return true; |
| } |
| |
| /*--- TSIntList operations --------------------------------------*/ |
| tsapi TSIntList |
| TSIntListCreate() |
| { |
| return (void *) create_queue(); /* this queue will be a list of int* */ |
| } |
| |
| /* usually, must be an empty list before destroying*/ |
| tsapi void |
| TSIntListDestroy(TSIntList intl) |
| { |
| int *iPtr; |
| |
| if (!intl) |
| return; |
| |
| /* dequeue each element and free it */ |
| while (!queue_is_empty((LLQ *) intl)) { |
| iPtr = (int *) dequeue((LLQ *) intl); |
| ats_free(iPtr); |
| } |
| |
| delete_queue((LLQ *) intl); |
| return; |
| } |
| |
| tsapi TSError |
| TSIntListEnqueue(TSIntList intl, int *elem) |
| { |
| int ret; |
| |
| ink_assert(intl && elem); |
| if (!intl || !elem) |
| return TS_ERR_PARAMS; |
| |
| ret = enqueue((LLQ *) intl, elem); /* returns TRUE=1 or FALSE=0 */ |
| if (ret == 0) { |
| return TS_ERR_FAIL; |
| } else { |
| return TS_ERR_OKAY; |
| } |
| } |
| |
| tsapi int * |
| TSIntListDequeue(TSIntList intl) |
| { |
| ink_assert(intl); |
| if (!intl || queue_is_empty((LLQ *) intl)) |
| return NULL; |
| |
| return (int *) dequeue((LLQ *) intl); |
| } |
| |
| tsapi bool |
| TSIntListIsEmpty(TSIntList intl) |
| { |
| ink_assert(intl); |
| if (!intl) |
| return true; |
| |
| return queue_is_empty((LLQ *) intl); |
| } |
| |
| tsapi int |
| TSIntListLen(TSIntList intl) |
| { |
| ink_assert(intl); |
| if (!intl) |
| return -1; |
| |
| return queue_len((LLQ *) intl); |
| } |
| |
| tsapi bool |
| TSIntListIsValid(TSIntList intl, int min, int max) |
| { |
| if (!intl) |
| return false; |
| |
| for (unsigned long i = 0; i < queue_len((LLQ *) intl); i++) { |
| int *item = (int *) dequeue((LLQ *) intl); |
| if (*item < min) { |
| return false; |
| } |
| if (*item > max) { |
| return false; |
| } |
| enqueue((LLQ *) intl, item); |
| } |
| return true; |
| } |
| |
| |
| // helper fn that sets default values for the info passed in |
| void |
| init_pdss_format(TSPdSsFormat * info) |
| { |
| info->pd_type = TS_PD_UNDEFINED; |
| info->pd_val = NULL; |
| info->sec_spec.active = 0; |
| info->sec_spec.time.hour_a = 0; |
| info->sec_spec.time.min_a = 0; |
| info->sec_spec.time.hour_b = 0; |
| info->sec_spec.time.min_b = 0; |
| info->sec_spec.src_ip = TS_INVALID_IP_ADDR; |
| info->sec_spec.prefix = NULL; |
| info->sec_spec.suffix = NULL; |
| info->sec_spec.port = TS_INVALID_PORT; |
| info->sec_spec.method = TS_METHOD_UNDEFINED; |
| info->sec_spec.scheme = TS_SCHEME_UNDEFINED; |
| } |
| |
| /*--- allocate/deallocate operations --------------------------------------*/ |
| tsapi TSEvent * |
| TSEventCreate(void) |
| { |
| TSEvent *event = (TSEvent *)ats_malloc(sizeof(TSEvent)); |
| |
| event->id = -1; |
| event->name = NULL; |
| event->description = NULL; |
| event->priority = TS_EVENT_PRIORITY_UNDEFINED; |
| |
| return event; |
| } |
| |
| tsapi void |
| TSEventDestroy(TSEvent * event) |
| { |
| if (event) { |
| ats_free(event->name); |
| ats_free(event->description); |
| ats_free(event); |
| } |
| return; |
| } |
| |
| tsapi TSRecordEle * |
| TSRecordEleCreate(void) |
| { |
| TSRecordEle *ele = (TSRecordEle *)ats_malloc(sizeof(TSRecordEle)); |
| |
| ele->rec_name = NULL; |
| ele->rec_type = TS_REC_UNDEFINED; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSRecordEleDestroy(TSRecordEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->rec_name); |
| if (ele->rec_type == TS_REC_STRING && ele->string_val) |
| ats_free(ele->string_val); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| tsapi TSIpAddrEle * |
| TSIpAddrEleCreate(void) |
| { |
| TSIpAddrEle *ele = (TSIpAddrEle *)ats_malloc(sizeof(TSIpAddrEle)); |
| |
| /* set default values */ |
| ele->type = TS_IP_UNDEFINED; |
| ele->ip_a = TS_INVALID_IP_ADDR; |
| ele->cidr_a = TS_INVALID_IP_CIDR; |
| ele->port_a = TS_INVALID_PORT; |
| ele->ip_b = TS_INVALID_IP_ADDR; |
| ele->cidr_b = TS_INVALID_IP_CIDR; |
| ele->port_b = TS_INVALID_PORT; |
| return ele; |
| } |
| |
| tsapi void |
| TSIpAddrEleDestroy(TSIpAddrEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->ip_a); |
| ats_free(ele->ip_b); |
| ats_free(ele); |
| } |
| |
| return; |
| } |
| |
| tsapi TSPortEle * |
| TSPortEleCreate(void) |
| { |
| TSPortEle *ele = (TSPortEle *)ats_malloc(sizeof(TSPortEle)); |
| |
| ele->port_a = TS_INVALID_PORT; |
| ele->port_b = TS_INVALID_PORT; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSPortEleDestroy(TSPortEle * ele) |
| { |
| ats_free(ele); |
| return; |
| } |
| |
| tsapi TSDomain * |
| TSDomainCreate() |
| { |
| TSDomain *ele = (TSDomain *)ats_malloc(sizeof(TSDomain)); |
| |
| ele->domain_val = NULL; |
| ele->port = TS_INVALID_PORT; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSDomainDestroy(TSDomain * ele) |
| { |
| if (ele) { |
| ats_free(ele->domain_val); |
| ats_free(ele); |
| } |
| } |
| |
| tsapi TSSspec * |
| TSSspecCreate(void) |
| { |
| TSSspec *sec_spec = (TSSspec *)ats_malloc(sizeof(TSSspec)); |
| |
| /* set defaults */ |
| sec_spec->active = 0; |
| (sec_spec->time).hour_a = 0; |
| (sec_spec->time).min_a = 0; |
| (sec_spec->time).hour_b = 0; |
| (sec_spec->time).min_b = 0; |
| sec_spec->src_ip = TS_INVALID_IP_ADDR; |
| sec_spec->prefix = NULL; |
| sec_spec->suffix = NULL; |
| sec_spec->port = NULL; |
| sec_spec->method = TS_METHOD_UNDEFINED; |
| sec_spec->scheme = TS_SCHEME_UNDEFINED; |
| return sec_spec; |
| } |
| |
| tsapi void |
| TSSspecDestroy(TSSspec * ele) |
| { |
| if (ele) { |
| ats_free(ele->prefix); |
| ats_free(ele->suffix); |
| if (ele->port) |
| TSPortEleDestroy(ele->port); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| tsapi TSPdSsFormat * |
| TSPdSsFormatCreate(void) |
| { |
| TSPdSsFormat *ele = (TSPdSsFormat *)ats_malloc(sizeof(TSPdSsFormat)); |
| |
| /* should set default values here */ |
| ele->pd_type = TS_PD_UNDEFINED; |
| ele->pd_val = NULL; |
| |
| ele->sec_spec.active = 0; |
| (ele->sec_spec.time).hour_a = -1; |
| (ele->sec_spec.time).min_a = -1; |
| (ele->sec_spec.time).hour_b = -1; |
| (ele->sec_spec.time).min_b = -1; |
| ele->sec_spec.src_ip = TS_INVALID_IP_ADDR; |
| ele->sec_spec.prefix = NULL; |
| ele->sec_spec.suffix = NULL; |
| ele->sec_spec.port = NULL; |
| ele->sec_spec.method = TS_METHOD_UNDEFINED; |
| ele->sec_spec.scheme = TS_SCHEME_UNDEFINED; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSPdSsFormatDestroy(TSPdSsFormat * ele) |
| { |
| if (ele) { |
| ats_free(ele->pd_val); |
| ats_free(ele->sec_spec.src_ip); |
| ats_free(ele->sec_spec.prefix); |
| ats_free(ele->sec_spec.suffix); |
| if (ele->sec_spec.port) |
| TSPortEleDestroy(ele->sec_spec.port); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * CacheObj |
| *-------------------------------------------------------------*/ |
| tsapi TSCacheEle * |
| TSCacheEleCreate(TSRuleTypeT type) |
| { |
| TSCacheEle *ele; |
| |
| if (type != TS_CACHE_NEVER && |
| type != TS_CACHE_IGNORE_NO_CACHE && |
| type != TS_CACHE_CLUSTER_CACHE_LOCAL && |
| type != TS_CACHE_IGNORE_CLIENT_NO_CACHE && |
| type != TS_CACHE_IGNORE_SERVER_NO_CACHE && |
| type != TS_CACHE_PIN_IN_CACHE && |
| type != TS_CACHE_REVALIDATE && |
| type != TS_CACHE_TTL_IN_CACHE && type != TS_CACHE_AUTH_CONTENT && type != TS_TYPE_UNDEFINED) |
| return NULL; // invalid type |
| |
| ele = (TSCacheEle *)ats_malloc(sizeof(TSCacheEle)); |
| |
| /* set defaults */ |
| ele->cfg_ele.type = type; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| init_pdss_format(&(ele->cache_info)); |
| ele->time_period.d = 0; |
| ele->time_period.h = 0; |
| ele->time_period.m = 0; |
| ele->time_period.s = 0; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSCacheEleDestroy(TSCacheEle * ele) |
| { |
| if (ele) { |
| TSPdSsFormatDestroy(&(ele->cache_info)); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * CongestionObj |
| *-------------------------------------------------------------*/ |
| // FIXME: for now use defaults specified in feature spec; the |
| // defaults though are configurable as records, so should use |
| // records values instead |
| tsapi TSCongestionEle * |
| TSCongestionEleCreate() |
| { |
| TSCongestionEle *ele = (TSCongestionEle *)ats_malloc(sizeof(TSCongestionEle)); |
| |
| /* set defaults */ |
| ele->cfg_ele.type = TS_CONGESTION; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| //init_pdss_format(&(ele->congestion_info)); |
| ele->pd_type = TS_PD_UNDEFINED; |
| ele->pd_val = NULL; |
| ele->prefix = NULL; |
| ele->port = TS_INVALID_PORT; |
| ele->scheme = TS_HTTP_CONGEST_PER_IP; |
| ele->max_connection_failures = 5; |
| ele->fail_window = 120; |
| ele->proxy_retry_interval = 10; |
| ele->client_wait_interval = 300; |
| ele->wait_interval_alpha = 30; |
| ele->live_os_conn_timeout = 60; |
| ele->live_os_conn_retries = 2; |
| ele->dead_os_conn_timeout = 15; |
| ele->dead_os_conn_retries = 1; |
| ele->max_connection = -1; |
| ele->error_page_uri = ats_strdup("congestion#retryAfter"); |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSCongestionEleDestroy(TSCongestionEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->pd_val); |
| ats_free(ele->prefix); |
| ats_free(ele->error_page_uri); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| |
| /*------------------------------------------------------------- |
| * HostingObj |
| *-------------------------------------------------------------*/ |
| tsapi TSHostingEle * |
| TSHostingEleCreate() |
| { |
| TSHostingEle *ele = (TSHostingEle *)ats_malloc(sizeof(TSHostingEle)); |
| |
| ele->cfg_ele.type = TS_HOSTING; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->pd_type = TS_PD_UNDEFINED; |
| ele->pd_val = NULL; |
| ele->volumes = TS_INVALID_LIST; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSHostingEleDestroy(TSHostingEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->pd_val); |
| if (ele->volumes) |
| TSIntListDestroy(ele->volumes); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * IcpObject |
| *-------------------------------------------------------------*/ |
| tsapi TSIcpEle * |
| TSIcpEleCreate() |
| { |
| TSIcpEle *ele = (TSIcpEle *)ats_malloc(sizeof(TSIcpEle)); |
| |
| /* set defaults */ |
| ele->cfg_ele.type = TS_ICP; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->peer_hostname = NULL; |
| ele->peer_host_ip_addr = TS_INVALID_IP_ADDR; |
| ele->peer_type = TS_ICP_UNDEFINED; |
| ele->peer_proxy_port = TS_INVALID_PORT; |
| ele->peer_icp_port = TS_INVALID_PORT; |
| ele->is_multicast = false; |
| ele->mc_ip_addr = TS_INVALID_IP_ADDR; |
| ele->mc_ttl = TS_MC_TTL_SINGLE_SUBNET; // default value |
| |
| return ele; |
| |
| } |
| |
| tsapi void |
| TSIcpEleDestroy(TSIcpEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->peer_hostname); |
| ats_free(ele->peer_host_ip_addr); |
| ats_free(ele->mc_ip_addr); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSIpAllowEle |
| *-------------------------------------------------------------*/ |
| tsapi TSIpAllowEle * |
| TSIpAllowEleCreate() |
| { |
| |
| TSIpAllowEle *ele = (TSIpAllowEle *)ats_malloc(sizeof(TSIpAllowEle)); |
| |
| ele->cfg_ele.type = TS_IP_ALLOW; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->src_ip_addr = TS_INVALID_IP_ADDR; |
| ele->action = TS_IP_ALLOW_UNDEFINED; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSIpAllowEleDestroy(TSIpAllowEle * ele) |
| { |
| if (ele) { |
| if (ele->src_ip_addr) |
| TSIpAddrEleDestroy(ele->src_ip_addr); |
| ats_free(ele); |
| } |
| return; |
| |
| } |
| |
| |
| /*------------------------------------------------------------- |
| * TSLogFilterEle |
| *-------------------------------------------------------------*/ |
| tsapi TSLogFilterEle * |
| TSLogFilterEleCreate() |
| { |
| TSLogFilterEle *ele = (TSLogFilterEle *)ats_malloc(sizeof(TSLogFilterEle)); |
| |
| ele->cfg_ele.type = TS_LOG_FILTER; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->action = TS_LOG_FILT_UNDEFINED; |
| ele->filter_name = NULL; |
| ele->log_field = NULL; |
| ele->compare_op = TS_LOG_COND_UNDEFINED; |
| ele->compare_str = NULL; |
| ele->compare_int = -1; |
| return ele; |
| } |
| |
| tsapi void |
| TSLogFilterEleDestroy(TSLogFilterEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->filter_name); |
| ats_free(ele->log_field); |
| ats_free(ele->compare_str); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSLogFormatEle |
| *-------------------------------------------------------------*/ |
| tsapi TSLogFormatEle * |
| TSLogFormatEleCreate() |
| { |
| TSLogFormatEle *ele = (TSLogFormatEle *)ats_malloc(sizeof(TSLogFormatEle)); |
| |
| ele->cfg_ele.type = TS_LOG_FORMAT; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->name = NULL; |
| ele->format = NULL; |
| ele->aggregate_interval_secs = 0; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSLogFormatEleDestroy(TSLogFormatEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->name); |
| ats_free(ele->format); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSLogObjectEle |
| *-------------------------------------------------------------*/ |
| tsapi TSLogObjectEle * |
| TSLogObjectEleCreate() |
| { |
| TSLogObjectEle *ele = (TSLogObjectEle *)ats_malloc(sizeof(TSLogObjectEle)); |
| |
| ele->cfg_ele.type = TS_LOG_OBJECT; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->format_name = NULL; |
| ele->file_name = NULL; |
| ele->log_mode = TS_LOG_MODE_UNDEFINED; |
| ele->collation_hosts = TS_INVALID_LIST; |
| ele->filters = TS_INVALID_LIST; |
| ele->protocols = TS_INVALID_LIST; |
| ele->server_hosts = TS_INVALID_LIST; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSLogObjectEleDestroy(TSLogObjectEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->format_name); |
| ats_free(ele->file_name); |
| if (ele->collation_hosts) |
| TSDomainListDestroy(ele->collation_hosts); |
| if (ele->filters) |
| TSStringListDestroy(ele->filters); |
| if (ele->protocols) |
| TSStringListDestroy(ele->protocols); |
| if (ele->server_hosts) |
| TSStringListDestroy(ele->server_hosts); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSParentProxyEleCreate |
| *-------------------------------------------------------------*/ |
| tsapi TSParentProxyEle * |
| TSParentProxyEleCreate(TSRuleTypeT type) |
| { |
| TSParentProxyEle *ele; |
| |
| if (type != TS_PP_PARENT && type != TS_PP_GO_DIRECT && type != TS_TYPE_UNDEFINED) |
| return NULL; |
| |
| ele = (TSParentProxyEle *)ats_malloc(sizeof(TSParentProxyEle)); |
| |
| ele->cfg_ele.type = type; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| init_pdss_format(&(ele->parent_info)); |
| ele->rr = TS_RR_NONE; |
| ele->proxy_list = TS_INVALID_LIST; |
| ele->direct = false; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSParentProxyEleDestroy(TSParentProxyEle * ele) |
| { |
| if (ele) { |
| TSPdSsFormatDestroy(&(ele->parent_info)); |
| if (ele->proxy_list) |
| TSDomainListDestroy(ele->proxy_list); |
| ats_free(ele); |
| } |
| |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSVolumeEle |
| *-------------------------------------------------------------*/ |
| tsapi TSVolumeEle * |
| TSVolumeEleCreate() |
| { |
| TSVolumeEle *ele = (TSVolumeEle *)ats_malloc(sizeof(TSVolumeEle)); |
| |
| ele->cfg_ele.type = TS_VOLUME; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->volume_num = 0; |
| ele->scheme = TS_VOLUME_UNDEFINED; |
| ele->volume_size = 0; |
| ele->size_format = TS_SIZE_FMT_UNDEFINED; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSVolumeEleDestroy(TSVolumeEle * ele) |
| { |
| ats_free(ele); |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSPluginEle |
| *-------------------------------------------------------------*/ |
| tsapi TSPluginEle * |
| TSPluginEleCreate() |
| { |
| TSPluginEle *ele = (TSPluginEle *)ats_malloc(sizeof(TSPluginEle)); |
| |
| ele->cfg_ele.type = TS_PLUGIN; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->name = NULL; |
| ele->args = TS_INVALID_LIST; |
| |
| return ele; |
| } |
| |
| tsapi void |
| TSPluginEleDestroy(TSPluginEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->name); |
| if (ele->args) |
| TSStringListDestroy(ele->args); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSRemapEle |
| *-------------------------------------------------------------*/ |
| TSRemapEle * |
| TSRemapEleCreate(TSRuleTypeT type) |
| { |
| TSRemapEle *ele; |
| |
| if (type != TS_REMAP_MAP && |
| type != TS_REMAP_REVERSE_MAP && |
| type != TS_REMAP_REDIRECT && type != TS_REMAP_REDIRECT_TEMP && type != TS_TYPE_UNDEFINED) |
| return NULL; |
| |
| ele = (TSRemapEle *)ats_malloc(sizeof(TSRemapEle)); |
| ele->cfg_ele.type = type; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->map = true; |
| ele->from_scheme = TS_SCHEME_UNDEFINED; |
| ele->from_host = NULL; |
| ele->from_port = TS_INVALID_PORT; |
| ele->from_path_prefix = NULL; |
| ele->to_scheme = TS_SCHEME_UNDEFINED; |
| ele->to_host = NULL; |
| ele->to_port = TS_INVALID_PORT; |
| ele->to_path_prefix = NULL; |
| |
| return ele; |
| } |
| |
| void |
| TSRemapEleDestroy(TSRemapEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->from_host); |
| ats_free(ele->from_path_prefix); |
| ats_free(ele->to_host); |
| ats_free(ele->to_path_prefix); |
| ats_free(ele); |
| } |
| } |
| |
| /*------------------------------------------------------------- |
| * TSSocksEle |
| *-------------------------------------------------------------*/ |
| TSSocksEle * |
| TSSocksEleCreate(TSRuleTypeT type) |
| { |
| TSSocksEle *ele = (TSSocksEle *)ats_malloc(sizeof(TSSocksEle)); |
| |
| ele->cfg_ele.type = type; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->ip_addrs = TS_INVALID_LIST; |
| ele->dest_ip_addr = TS_INVALID_IP_ADDR; |
| ele->socks_servers = TS_INVALID_LIST; |
| ele->rr = TS_RR_NONE; |
| ele->username = NULL; |
| ele->password = NULL; |
| |
| return ele; |
| } |
| |
| void |
| TSSocksEleDestroy(TSSocksEle * ele) |
| { |
| if (ele) { |
| if (ele->ip_addrs) |
| TSIpAddrListDestroy(ele->ip_addrs); |
| if (ele->dest_ip_addr) |
| TSIpAddrEleDestroy(ele->dest_ip_addr); |
| if (ele->socks_servers) |
| TSDomainListDestroy(ele->socks_servers); |
| ats_free(ele->username); |
| ats_free(ele->password); |
| ats_free(ele); |
| } |
| } |
| |
| /*------------------------------------------------------------- |
| * TSSplitDnsEle |
| *-------------------------------------------------------------*/ |
| TSSplitDnsEle * |
| TSSplitDnsEleCreate() |
| { |
| TSSplitDnsEle *ele = (TSSplitDnsEle *)ats_malloc(sizeof(TSSplitDnsEle)); |
| |
| ele->cfg_ele.type = TS_SPLIT_DNS; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->pd_type = TS_PD_UNDEFINED; |
| ele->pd_val = NULL; |
| ele->dns_servers_addrs = TS_INVALID_LIST; |
| ele->def_domain = NULL; |
| ele->search_list = TS_INVALID_LIST; |
| |
| return ele; |
| } |
| |
| void |
| TSSplitDnsEleDestroy(TSSplitDnsEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->pd_val); |
| if (ele->dns_servers_addrs) |
| TSDomainListDestroy(ele->dns_servers_addrs); |
| ats_free(ele->def_domain); |
| if (ele->search_list) |
| TSDomainListDestroy(ele->search_list); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSStorageEle |
| *-------------------------------------------------------------*/ |
| TSStorageEle * |
| TSStorageEleCreate() |
| { |
| TSStorageEle *ele = (TSStorageEle *)ats_malloc(sizeof(TSStorageEle)); |
| |
| ele->cfg_ele.type = TS_STORAGE; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->pathname = NULL; |
| ele->size = -1; |
| |
| return ele; |
| } |
| |
| void |
| TSStorageEleDestroy(TSStorageEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->pathname); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSUpdateEle |
| *-------------------------------------------------------------*/ |
| TSUpdateEle * |
| TSUpdateEleCreate() |
| { |
| TSUpdateEle *ele = (TSUpdateEle *)ats_malloc(sizeof(TSUpdateEle)); |
| |
| ele->cfg_ele.type = TS_UPDATE_URL; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->url = NULL; |
| ele->headers = TS_INVALID_LIST; |
| ele->offset_hour = -1; |
| ele->interval = -1; |
| ele->recursion_depth = 0; |
| |
| return ele; |
| } |
| |
| void |
| TSUpdateEleDestroy(TSUpdateEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->url); |
| if (ele->headers) |
| TSStringListDestroy(ele->headers); |
| ats_free(ele); |
| } |
| return; |
| } |
| |
| /*------------------------------------------------------------- |
| * TSVirtIpAddrEle |
| *-------------------------------------------------------------*/ |
| TSVirtIpAddrEle * |
| TSVirtIpAddrEleCreate() |
| { |
| TSVirtIpAddrEle *ele = (TSVirtIpAddrEle *)ats_malloc(sizeof(TSVirtIpAddrEle)); |
| |
| ele->cfg_ele.type = TS_VADDRS; |
| ele->cfg_ele.error = TS_ERR_OKAY; |
| ele->intr = NULL; |
| ele->sub_intr = -1; |
| ele->ip_addr = TS_INVALID_IP_ADDR; |
| |
| return ele; |
| } |
| |
| void |
| TSVirtIpAddrEleDestroy(TSVirtIpAddrEle * ele) |
| { |
| if (ele) { |
| ats_free(ele->intr); |
| ats_free(ele->ip_addr); |
| ats_free(ele); |
| } |
| } |
| |
| /*************************************************************************** |
| * API Core |
| ***************************************************************************/ |
| |
| /*--- statistics operations ----------------------------------------------- */ |
| tsapi TSError |
| TSStatsReset(bool cluster, const char *name) |
| { |
| return StatsReset(cluster, name); |
| } |
| |
| /*--- variable operations ------------------------------------------------- */ |
| /* Call the CfgFileIO variable operations */ |
| |
| tsapi TSError |
| TSRecordGet(char *rec_name, TSRecordEle * rec_val) |
| { |
| return MgmtRecordGet(rec_name, rec_val); |
| } |
| |
| TSError |
| TSRecordGetInt(const char *rec_name, TSInt * int_val) |
| { |
| TSError ret = TS_ERR_OKAY; |
| |
| TSRecordEle *ele = TSRecordEleCreate(); |
| ret = MgmtRecordGet(rec_name, ele); |
| if (ret != TS_ERR_OKAY) |
| goto END; |
| |
| *int_val = ele->int_val; |
| |
| END: |
| TSRecordEleDestroy(ele); |
| return ret; |
| } |
| |
| TSError |
| TSRecordGetCounter(const char *rec_name, TSCounter * counter_val) |
| { |
| TSError ret; |
| |
| TSRecordEle *ele = TSRecordEleCreate(); |
| ret = MgmtRecordGet(rec_name, ele); |
| if (ret != TS_ERR_OKAY) |
| goto END; |
| *counter_val = ele->counter_val; |
| |
| END: |
| TSRecordEleDestroy(ele); |
| return ret; |
| } |
| |
| TSError |
| TSRecordGetFloat(const char *rec_name, TSFloat * float_val) |
| { |
| TSError ret; |
| |
| TSRecordEle *ele = TSRecordEleCreate(); |
| ret = MgmtRecordGet(rec_name, ele); |
| if (ret != TS_ERR_OKAY) |
| goto END; |
| *float_val = ele->float_val; |
| |
| END: |
| TSRecordEleDestroy(ele); |
| return ret; |
| } |
| |
| TSError |
| TSRecordGetString(const char *rec_name, TSString *string_val) |
| { |
| TSError ret; |
| |
| TSRecordEle *ele = TSRecordEleCreate(); |
| ret = MgmtRecordGet(rec_name, ele); |
| if (ret != TS_ERR_OKAY) |
| goto END; |
| |
| *string_val = ats_strdup(ele->string_val); |
| |
| END: |
| TSRecordEleDestroy(ele); |
| return ret; |
| } |
| |
| |
| /*------------------------------------------------------------------------- |
| * TSRecordGetMlt |
| *------------------------------------------------------------------------- |
| * Purpose: Retrieves list of record values specified in the rec_names list |
| * Input: rec_names - list of record names to retrieve |
| * rec_vals - queue of TSRecordEle* that correspons to rec_names |
| * Output: If at any point, while retrieving one of the records there's a |
| * a failure then the entire process is aborted, all the allocated |
| * TSRecordEle's are deallocated and TS_ERR_FAIL is returned. |
| * Note: rec_names is not freed; if function is successful, the rec_names |
| * list is unchanged! |
| * |
| * IS THIS FUNCTION AN ATOMIC TRANSACTION? Technically, all the variables |
| * requested should refer to the same config file. But a lock is only |
| * put on each variable it is looked up. Need to be able to lock |
| * a file while retrieving all the requested records! |
| */ |
| |
| tsapi TSError |
| TSRecordGetMlt(TSStringList rec_names, TSList rec_vals) |
| { |
| TSRecordEle *ele; |
| char *rec_name; |
| int num_recs, i, j; |
| TSError ret; |
| |
| if (!rec_names || !rec_vals) |
| return TS_ERR_PARAMS; |
| |
| num_recs = queue_len((LLQ *) rec_names); |
| for (i = 0; i < num_recs; i++) { |
| rec_name = (char *) dequeue((LLQ *) rec_names); // remove name from list |
| if (!rec_name) |
| return TS_ERR_PARAMS; // NULL is invalid record name |
| |
| ele = TSRecordEleCreate(); |
| |
| ret = MgmtRecordGet(rec_name, ele); |
| enqueue((LLQ *) rec_names, rec_name); // return name to list |
| |
| if (ret != TS_ERR_OKAY) { // RecordGet failed |
| // need to free all the ele's allocated by MgmtRecordGet so far |
| TSRecordEleDestroy(ele); |
| for (j = 0; j < i; j++) { |
| ele = (TSRecordEle *) dequeue((LLQ *) rec_vals); |
| if (ele) |
| TSRecordEleDestroy(ele); |
| } |
| return ret; |
| } |
| enqueue((LLQ *) rec_vals, ele); // all is good; add ele to end of list |
| } |
| |
| return TS_ERR_OKAY; |
| } |
| |
| tsapi TSError |
| TSRecordGetMatchMlt(const char * regex, TSList rec_vals) |
| { |
| if (!regex || !rec_vals) { |
| return TS_ERR_PARAMS; |
| } |
| |
| return MgmtRecordGetMatching(regex, rec_vals); |
| } |
| |
| tsapi TSError |
| TSRecordSet(const char *rec_name, const char *val, TSActionNeedT * action_need) |
| { |
| return MgmtRecordSet(rec_name, val, action_need); |
| } |
| |
| |
| tsapi TSError |
| TSRecordSetInt(const char *rec_name, TSInt int_val, TSActionNeedT * action_need) |
| { |
| return MgmtRecordSetInt(rec_name, int_val, action_need); |
| } |
| |
| tsapi TSError |
| TSRecordSetCounter(const char *rec_name, TSCounter counter_val, TSActionNeedT * action_need) |
| { |
| return MgmtRecordSetCounter(rec_name, counter_val, action_need); |
| } |
| |
| tsapi TSError |
| TSRecordSetFloat(const char *rec_name, TSFloat float_val, TSActionNeedT * action_need) |
| { |
| return MgmtRecordSetFloat(rec_name, float_val, action_need); |
| } |
| |
| tsapi TSError |
| TSRecordSetString(const char *rec_name, const char *str_val, TSActionNeedT * action_need) |
| { |
| return MgmtRecordSetString(rec_name, str_val, action_need); |
| } |
| |
| |
| /*------------------------------------------------------------------------- |
| * TSRecordSetMlt |
| *------------------------------------------------------------------------- |
| * Basically iterates through each RecordEle in rec_list and calls the |
| * appropriate "MgmtRecordSetxx" function for that record |
| * Input: rec_list - queue of TSRecordEle*; each TSRecordEle* must have |
| * a valid record name (remains unchanged on return) |
| * Output: if there is an error during the setting of one of the variables then |
| * will continue to try to set the other variables. Error response will |
| * indicate though that not all set operations were successful. |
| * TS_ERR_OKAY is returned if all the records are set successfully |
| * Note: Determining the action needed is more complex b/c need to keep |
| * track of which record change is the most drastic out of the group of |
| * records; action_need will be set to the most severe action needed of |
| * all the "Set" calls |
| */ |
| tsapi TSError |
| TSRecordSetMlt(TSList rec_list, TSActionNeedT * action_need) |
| { |
| int num_recs, ret, i; |
| TSRecordEle *ele; |
| TSError status = TS_ERR_OKAY; |
| TSActionNeedT top_action_req = TS_ACTION_UNDEFINED; |
| |
| if (!rec_list || !action_need) |
| return TS_ERR_PARAMS; |
| |
| num_recs = queue_len((LLQ *) rec_list); |
| |
| for (i = 0; i < num_recs; i++) { |
| ele = (TSRecordEle *) dequeue((LLQ *) rec_list); |
| if (ele) { |
| switch (ele->rec_type) { |
| case TS_REC_INT: |
| ret = MgmtRecordSetInt(ele->rec_name, ele->int_val, action_need); |
| break; |
| case TS_REC_COUNTER: |
| ret = MgmtRecordSetCounter(ele->rec_name, ele->counter_val, action_need); |
| break; |
| case TS_REC_FLOAT: |
| ret = MgmtRecordSetFloat(ele->rec_name, ele->float_val, action_need); |
| break; |
| case TS_REC_STRING: |
| ret = MgmtRecordSetString(ele->rec_name, ele->string_val, action_need); |
| break; |
| default: |
| ret = TS_ERR_FAIL; |
| break; |
| }; /* end of switch (ele->rec_type) */ |
| if (ret != TS_ERR_OKAY) |
| status = TS_ERR_FAIL; |
| |
| // keep track of most severe action; reset if needed |
| // the TSACtionNeedT should be listed such that most severe actions have |
| // a lower number (so most severe action == 0) |
| if (*action_need < top_action_req) // a more severe action |
| top_action_req = *action_need; |
| } |
| enqueue((LLQ *) rec_list, ele); |
| } |
| |
| // set the action_need to be the most sever action needed of all the "set" calls |
| *action_need = top_action_req; |
| |
| return status; |
| } |
| |
| /*--- api initialization and shutdown -------------------------------------*/ |
| tsapi TSError |
| TSInit(const char *socket_path, TSInitOptionT options) |
| { |
| return Init(socket_path, options); |
| } |
| |
| tsapi TSError |
| TSTerminate() |
| { |
| return Terminate(); |
| } |
| |
| /*--- plugin initialization -----------------------------------------------*/ |
| inkexp extern void |
| TSPluginInit(int /* argc ATS_UNUSED */, const char */* argv ATS_UNUSED */[]) |
| { |
| } |
| |
| /*--- network operations --------------------------------------------------*/ |
| tsapi TSError |
| TSConnect(TSIpAddr /* ip_addr ATS_UNUSED */, int /* port ATS_UNUSED */) |
| { |
| return TS_ERR_OKAY; |
| } |
| tsapi TSError |
| TSDisconnectCbRegister(TSDisconnectFunc * /* func ATS_UNUSED */, void * /* data ATS_UNUSED */) |
| { |
| return TS_ERR_OKAY; |
| } |
| tsapi TSError |
| TSDisconnectRetrySet(int /* retries ATS_UNUSED */, int /* retry_sleep_msec ATS_UNUSED */) |
| { |
| return TS_ERR_OKAY; |
| } |
| tsapi TSError |
| TSDisconnect() |
| { |
| return TS_ERR_OKAY; |
| } |
| |
| /*--- control operations --------------------------------------------------*/ |
| /* NOTE: these operations are wrappers that make direct calls to the CoreAPI */ |
| |
| /* TSProxyStateGet: get the proxy state (on/off) |
| * Input: <none> |
| * Output: proxy state (on/off) |
| */ |
| tsapi TSProxyStateT |
| TSProxyStateGet() |
| { |
| return ProxyStateGet(); |
| } |
| |
| /* TSProxyStateSet: set the proxy state (on/off) |
| * Input: proxy_state - set to on/off |
| * clear - start TS with cache clearing option, |
| * when stopping TS should always be TS_CACHE_CLEAR_OFF |
| * Output: TSError |
| */ |
| tsapi TSError |
| TSProxyStateSet(TSProxyStateT proxy_state, TSCacheClearT clear) |
| { |
| return ProxyStateSet(proxy_state, clear); |
| } |
| |
| /* TSReconfigure: tell traffic_server to re-read its configuration files |
| * Input: <none> |
| * Output: TSError |
| */ |
| tsapi TSError |
| TSReconfigure() |
| { |
| return Reconfigure(); |
| } |
| |
| /* TSRestart: restarts Traffic Server |
| * Input: cluster - local or cluster-wide |
| * Output: TSError |
| */ |
| tsapi TSError |
| TSRestart(bool cluster) |
| { |
| return Restart(cluster); |
| } |
| |
| /* TSHardRestart: a traffic_cop restart (restarts TM and TS), |
| * essentially does a "start_traffic_server"/"stop_traffic_server" sequence |
| * Input: <none> |
| * Output: TSError |
| * Note: only for remote API clients |
| */ |
| /* CAN ONLY BE IMPLEMENTED ON THE REMOTE SIDE !!! */ |
| tsapi TSError |
| TSHardRestart() |
| { |
| return HardRestart(); // should return TS_ERR_FAIL |
| } |
| |
| /* TSActionDo: based on TSActionNeedT, will take appropriate action |
| * Input: action - action that needs to be taken |
| * Output: TSError |
| */ |
| tsapi TSError |
| TSActionDo(TSActionNeedT action) |
| { |
| TSError ret; |
| |
| switch (action) { |
| case TS_ACTION_SHUTDOWN: |
| ret = HardRestart(); |
| break; |
| case TS_ACTION_RESTART: |
| ret = Restart(true); // cluster wide by default? |
| break; |
| case TS_ACTION_RECONFIGURE: |
| ret = Reconfigure(); |
| break; |
| case TS_ACTION_DYNAMIC: |
| /* do nothing - change takes effect immediately */ |
| return TS_ERR_OKAY; |
| default: |
| return TS_ERR_FAIL; |
| } |
| |
| return ret; |
| } |
| |
| /* TSBouncer: restarts the traffic_server process(es) |
| * Input: cluster - local or cluster-wide |
| * Output: TSError |
| */ |
| tsapi TSError |
| TSBounce(bool cluster) |
| { |
| return Bounce(cluster); |
| } |
| |
| tsapi TSError |
| TSStorageDeviceCmdOffline(char const* dev) |
| { |
| return StorageDeviceCmdOffline(dev); |
| } |
| |
| |
| /*--- diags output operations ---------------------------------------------*/ |
| tsapi void |
| TSDiags(TSDiagsT mode, const char *fmt, ...) |
| { |
| // need to find way to pass arguments to the function |
| va_list ap; |
| |
| va_start(ap, fmt); // initialize the argument pointer ap |
| Diags(mode, fmt, ap); |
| va_end(ap); |
| |
| return; |
| } |
| |
| /* NOTE: user must deallocate the memory for the string returned */ |
| char * |
| TSGetErrorMessage(TSError err_id) |
| { |
| char msg[1024]; // need to define a MAX_ERR_MSG_SIZE??? |
| char *err_msg = NULL; |
| |
| switch (err_id) { |
| case TS_ERR_OKAY: |
| snprintf(msg, sizeof(msg), "[%d] Everything's looking good.", err_id); |
| break; |
| case TS_ERR_READ_FILE: /* Error occur in reading file */ |
| snprintf(msg, sizeof(msg), "[%d] Unable to find/open file for reading.", err_id); |
| break; |
| case TS_ERR_WRITE_FILE: /* Error occur in writing file */ |
| snprintf(msg, sizeof(msg), "[%d] Unable to find/open file for writing.", err_id); |
| break; |
| case TS_ERR_PARSE_CONFIG_RULE: /* Error in parsing configuration file */ |
| snprintf(msg, sizeof(msg), "[%d] Error parsing configuration file.", err_id); |
| break; |
| case TS_ERR_INVALID_CONFIG_RULE: /* Invalid Configuration Rule */ |
| snprintf(msg, sizeof(msg), "[%d] Invalid configuration rule reached.", err_id); |
| break; |
| case TS_ERR_NET_ESTABLISH: |
| snprintf(msg, sizeof(msg), "[%d] Error establishing socket connection.", err_id); |
| break; |
| case TS_ERR_NET_READ: /* Error reading from socket */ |
| snprintf(msg, sizeof(msg), "[%d] Error reading from socket.", err_id); |
| break; |
| case TS_ERR_NET_WRITE: /* Error writing to socket */ |
| snprintf(msg, sizeof(msg), "[%d] Error writing to socket.", err_id); |
| break; |
| case TS_ERR_NET_EOF: /* Hit socket EOF */ |
| snprintf(msg, sizeof(msg), "[%d] Reached socket EOF.", err_id); |
| break; |
| case TS_ERR_NET_TIMEOUT: /* Timed out waiting for socket read */ |
| snprintf(msg, sizeof(msg), "[%d] Timed out waiting for socket read.", err_id); |
| break; |
| case TS_ERR_SYS_CALL: /* Error in sys/utility call, eg.malloc */ |
| snprintf(msg, sizeof(msg), "[%d] Error in basic system/utility call.", err_id); |
| break; |
| case TS_ERR_PARAMS: /* Invalid parameters for a fn */ |
| snprintf(msg, sizeof(msg), "[%d] Invalid parameters passed into function call.", err_id); |
| break; |
| case TS_ERR_FAIL: |
| snprintf(msg, sizeof(msg), "[%d] Generic Fail message (ie. CoreAPI call).", err_id); |
| break; |
| |
| default: |
| snprintf(msg, sizeof(msg), "[%d] Invalid error type.", err_id); |
| break; |
| } |
| |
| err_msg = ats_strdup(msg); |
| return err_msg; |
| } |
| |
| |
| /*--- password operations -------------------------------------------------*/ |
| tsapi TSError |
| TSEncryptPassword(char *passwd, char **e_passwd) |
| { |
| INK_DIGEST_CTX md5_context; |
| char passwd_md5[16]; |
| char *passwd_md5_str; |
| int passwd_md5_str_len = 32; |
| |
| ink_assert(passwd); |
| ink_assert(TS_ENCRYPT_PASSWD_LEN <= passwd_md5_str_len); |
| |
| const size_t md5StringSize = (passwd_md5_str_len + 1) * sizeof(char); |
| passwd_md5_str = (char *)ats_malloc(md5StringSize); |
| |
| ink_code_incr_md5_init(&md5_context); |
| ink_code_incr_md5_update(&md5_context, passwd, strlen(passwd)); |
| ink_code_incr_md5_final(passwd_md5, &md5_context); |
| ink_code_md5_stringify(passwd_md5_str, md5StringSize, passwd_md5); |
| |
| // use only a subset of the MD5 string |
| passwd_md5_str[TS_ENCRYPT_PASSWD_LEN] = '\0'; |
| *e_passwd = passwd_md5_str; |
| |
| return TS_ERR_OKAY; |
| } |
| |
| /*--- direct file operations ----------------------------------------------*/ |
| tsapi TSError |
| TSConfigFileRead(TSFileNameT file, char **text, int *size, int *version) |
| { |
| return ReadFile(file, text, size, version); |
| } |
| |
| tsapi TSError |
| TSConfigFileWrite(TSFileNameT file, char *text, int size, int version) |
| { |
| return WriteFile(file, text, size, version); |
| } |
| |
| |
| /* ReadFromUrl: reads a remotely located config file into a buffer |
| * Input: url - remote location of the file |
| * header - a buffer is allocated on the header char* pointer |
| * headerSize - the size of the header buffer is returned |
| * body - a buffer is allocated on the body char* pointer |
| * bodySize - the size of the body buffer is returned |
| * Output: TSError - TS_ERR_OKAY if succeed, TS_ERR_FAIL otherwise |
| * Obsolete: tsapi TSError TSReadFromUrl (char *url, char **text, int *size); |
| * NOTE: The URL can be expressed in the following forms: |
| * - http://www.example.com:80/products/network/index.html |
| * - http://www.example.com/products/network/index.html |
| * - http://www.example.com/products/network/ |
| * - http://www.example.com/ |
| * - http://www.example.com |
| * - www.example.com |
| * NOTE: header and headerSize can be NULL |
| */ |
| tsapi TSError |
| TSReadFromUrl(char *url, char **header, int *headerSize, char **body, int *bodySize) |
| { |
| //return ReadFromUrl(url, header, headerSize, body, bodySize); |
| return TSReadFromUrlEx(url, header, headerSize, body, bodySize, URL_TIMEOUT); |
| |
| } |
| |
| tsapi TSError |
| TSReadFromUrlEx(const char *url, char **header, int *headerSize, char **body, int *bodySize, int timeout) |
| { |
| int hFD = -1; |
| char *httpHost = NULL; |
| char *httpPath = NULL; |
| int httpPort = HTTP_PORT; |
| int bufsize = URL_BUFSIZE; |
| char buffer[URL_BUFSIZE]; |
| char request[BUFSIZE]; |
| char *hdr_temp; |
| char *bdy_temp; |
| TSError status = TS_ERR_OKAY; |
| |
| // Sanity check |
| if (!url) |
| return TS_ERR_FAIL; |
| if (timeout < 0) { |
| timeout = URL_TIMEOUT; |
| } |
| // Chop the protocol part, if it exists |
| const char *doubleSlash = strstr(url, "//"); |
| if (doubleSlash) { |
| url = doubleSlash + 2; // advance two positions to get rid of leading '//' |
| } |
| // the path starts after the first occurrence of '/' |
| const char *tempPath = strstr(url, "/"); |
| char *host_and_port; |
| if (tempPath) { |
| host_and_port = ats_strndup(url, strlen(url) - strlen(tempPath)); |
| tempPath += 1; // advance one position to get rid of leading '/' |
| httpPath = ats_strdup(tempPath); |
| } else { |
| host_and_port = ats_strdup(url); |
| httpPath = ats_strdup(""); |
| } |
| |
| // the port proceed by a ":", if it exists |
| char *colon = strstr(host_and_port, ":"); |
| if (colon) { |
| httpHost = ats_strndup(host_and_port, strlen(host_and_port) - strlen(colon)); |
| colon += 1; // advance one position to get rid of leading ':' |
| httpPort = ink_atoi(colon); |
| if (httpPort <= 0) |
| httpPort = HTTP_PORT; |
| } else { |
| httpHost = ats_strdup(host_and_port); |
| } |
| ats_free(host_and_port); |
| |
| hFD = connectDirect(httpHost, httpPort, timeout); |
| if (hFD == -1) { |
| status = TS_ERR_NET_ESTABLISH; |
| goto END; |
| } |
| |
| /* sending the HTTP request via the established socket */ |
| snprintf(request, BUFSIZE, "http://%s:%d/%s", httpHost, httpPort, httpPath); |
| if ((status = sendHTTPRequest(hFD, request, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| memset(buffer, 0, bufsize); /* empty the buffer */ |
| if ((status = readHTTPResponse(hFD, buffer, bufsize, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((status = parseHTTPResponse(buffer, &hdr_temp, headerSize, &bdy_temp, bodySize)) |
| != TS_ERR_OKAY) |
| goto END; |
| |
| if (header && headerSize) |
| *header = ats_strndup(hdr_temp, *headerSize); |
| *body = ats_strndup(bdy_temp, *bodySize); |
| |
| END: |
| ats_free(httpHost); |
| ats_free(httpPath); |
| |
| return status; |
| } |
| |
| /*--- cache inspector operations -------------------------------------------*/ |
| |
| tsapi TSError |
| TSLookupFromCacheUrl(TSString url, TSString * info) |
| { |
| TSError err = TS_ERR_OKAY; |
| int fd; |
| char request[BUFSIZE]; |
| char response[URL_BUFSIZE]; |
| char *header; |
| char *body; |
| int hdr_size; |
| int bdy_size; |
| int timeout = URL_TIMEOUT; |
| TSInt ts_port = 8080; |
| |
| if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { |
| err = TS_ERR_FAIL; |
| goto END; |
| } |
| snprintf(request, BUFSIZE, "http://{cache}/lookup_url?url=%s", url); |
| if ((err = sendHTTPRequest(fd, request, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| memset(response, 0, URL_BUFSIZE); |
| if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) |
| goto END; |
| |
| *info = ats_strndup(body, bdy_size); |
| |
| END: |
| return err; |
| } |
| |
| tsapi TSError |
| TSLookupFromCacheUrlRegex(TSString url_regex, TSString * list) |
| { |
| TSError err = TS_ERR_OKAY; |
| int fd = -1; |
| char request[BUFSIZE]; |
| char response[URL_BUFSIZE]; |
| char *header; |
| char *body; |
| int hdr_size; |
| int bdy_size; |
| int timeout = -1; |
| TSInt ts_port = 8080; |
| |
| if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { |
| err = TS_ERR_FAIL; |
| goto END; |
| } |
| snprintf(request, BUFSIZE, "http://{cache}/lookup_regex?url=%s", url_regex); |
| if ((err = sendHTTPRequest(fd, request, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| memset(response, 0, URL_BUFSIZE); |
| if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) |
| goto END; |
| |
| *list = ats_strndup(body, bdy_size); |
| END: |
| return err; |
| } |
| |
| tsapi TSError |
| TSDeleteFromCacheUrl(TSString url, TSString * info) |
| { |
| TSError err = TS_ERR_OKAY; |
| int fd = -1; |
| char request[BUFSIZE]; |
| char response[URL_BUFSIZE]; |
| char *header; |
| char *body; |
| int hdr_size; |
| int bdy_size; |
| int timeout = URL_TIMEOUT; |
| TSInt ts_port = 8080; |
| |
| if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { |
| err = TS_ERR_FAIL; |
| goto END; |
| } |
| snprintf(request, BUFSIZE, "http://{cache}/delete_url?url=%s", url); |
| if ((err = sendHTTPRequest(fd, request, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| memset(response, 0, URL_BUFSIZE); |
| if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) |
| goto END; |
| |
| *info = ats_strndup(body, bdy_size); |
| |
| END: |
| return err; |
| } |
| |
| tsapi TSError |
| TSDeleteFromCacheUrlRegex(TSString url_regex, TSString * list) |
| { |
| TSError err = TS_ERR_OKAY; |
| int fd = -1; |
| char request[BUFSIZE]; |
| char response[URL_BUFSIZE]; |
| char *header; |
| char *body; |
| int hdr_size; |
| int bdy_size; |
| int timeout = -1; |
| TSInt ts_port = 8080; |
| |
| if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { |
| err = TS_ERR_FAIL; |
| goto END; |
| } |
| snprintf(request, BUFSIZE, "http://{cache}/delete_regex?url=%s", url_regex); |
| if ((err = sendHTTPRequest(fd, request, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| memset(response, 0, URL_BUFSIZE); |
| if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) |
| goto END; |
| |
| *list = ats_strndup(body, bdy_size); |
| END: |
| return err; |
| } |
| |
| tsapi TSError |
| TSInvalidateFromCacheUrlRegex(TSString url_regex, TSString * list) |
| { |
| TSError err = TS_ERR_OKAY; |
| int fd = -1; |
| char request[BUFSIZE]; |
| char response[URL_BUFSIZE]; |
| char *header; |
| char *body; |
| int hdr_size; |
| int bdy_size; |
| int timeout = -1; |
| TSInt ts_port = 8080; |
| |
| if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) { |
| err = TS_ERR_FAIL; |
| goto END; |
| } |
| snprintf(request, BUFSIZE, "http://{cache}/invalidate_regex?url=%s", url_regex); |
| if ((err = sendHTTPRequest(fd, request, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| memset(response, 0, URL_BUFSIZE); |
| if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, (uint64_t) timeout)) != TS_ERR_OKAY) |
| goto END; |
| |
| if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) |
| goto END; |
| |
| *list = ats_strndup(body, bdy_size); |
| END: |
| return err; |
| } |
| |
| /*--- snapshot operations -------------------------------------------------*/ |
| tsapi TSError |
| TSSnapshotTake(char *snapshot_name) |
| { |
| return SnapshotTake(snapshot_name); |
| } |
| |
| tsapi TSError |
| TSSnapshotRestore(char *snapshot_name) |
| { |
| return SnapshotRestore(snapshot_name); |
| } |
| |
| tsapi TSError |
| TSSnapshotRemove(char *snapshot_name) |
| { |
| return SnapshotRemove(snapshot_name); |
| } |
| |
| tsapi TSError |
| TSSnapshotGetMlt(TSStringList snapshots) |
| { |
| return SnapshotGetMlt((LLQ *) snapshots); |
| } |
| |
| /*--- events --------------------------------------------------------------*/ |
| tsapi TSError |
| TSEventSignal(char *event_name, ...) |
| { |
| va_list ap; |
| TSError ret; |
| |
| va_start(ap, event_name); // initialize the argument pointer ap |
| ret = EventSignal(event_name, ap); |
| va_end(ap); |
| return ret; |
| } |
| |
| tsapi TSError |
| TSEventResolve(char *event_name) |
| { |
| return EventResolve(event_name); |
| } |
| |
| tsapi TSError |
| TSActiveEventGetMlt(TSList active_events) |
| { |
| return ActiveEventGetMlt((LLQ *) active_events); |
| } |
| |
| tsapi TSError |
| TSEventIsActive(char *event_name, bool * is_current) |
| { |
| return EventIsActive(event_name, is_current); |
| } |
| |
| tsapi TSError |
| TSEventSignalCbRegister(char *event_name, TSEventSignalFunc func, void *data) |
| { |
| return EventSignalCbRegister(event_name, func, data); |
| } |
| |
| tsapi TSError |
| TSEventSignalCbUnregister(char *event_name, TSEventSignalFunc func) |
| { |
| return EventSignalCbUnregister(event_name, func); |
| } |
| |
| /*************************************************************************** |
| * API Helper Functions for Data Carrier Structures |
| ***************************************************************************/ |
| |
| /*--- abstracted file operations ------------------------------------------*/ |
| |
| /* calls teh CfgContext class constructor */ |
| tsapi TSCfgContext |
| TSCfgContextCreate(TSFileNameT file) |
| { |
| return ((void *) CfgContextCreate(file)); |
| } |
| |
| /* calls the CfgContext class destructor */ |
| tsapi TSError |
| TSCfgContextDestroy(TSCfgContext ctx) |
| { |
| return (CfgContextDestroy((CfgContext *) ctx)); |
| } |
| |
| tsapi TSError |
| TSCfgContextCommit(TSCfgContext ctx, TSActionNeedT * /* action_need ATS_UNUSED */, TSIntList errRules) |
| { |
| return (CfgContextCommit((CfgContext *) ctx, (LLQ *) errRules)); |
| } |
| |
| tsapi TSError |
| TSCfgContextGet(TSCfgContext ctx) |
| { |
| return (CfgContextGet((CfgContext *) ctx)); |
| } |
| |
| /*--- helper operations ---------------------------------------------------*/ |
| /* returns number of ele's in the TSCfgContext */ |
| int |
| TSCfgContextGetCount(TSCfgContext ctx) |
| { |
| return CfgContextGetCount((CfgContext *) ctx); |
| } |
| |
| /* user must typecast the TSCfgEle to appropriate TSEle before using */ |
| TSCfgEle * |
| TSCfgContextGetEleAt(TSCfgContext ctx, int index) |
| { |
| return CfgContextGetEleAt((CfgContext *) ctx, index); |
| } |
| |
| /* iterator */ |
| TSCfgEle * |
| TSCfgContextGetFirst(TSCfgContext ctx, TSCfgIterState * state) |
| { |
| return CfgContextGetFirst((CfgContext *) ctx, state); |
| } |
| |
| TSCfgEle * |
| TSCfgContextGetNext(TSCfgContext ctx, TSCfgIterState * state) |
| { |
| return CfgContextGetNext((CfgContext *) ctx, state); |
| } |
| |
| TSError |
| TSCfgContextMoveEleUp(TSCfgContext ctx, int index) |
| { |
| return CfgContextMoveEleUp((CfgContext *) ctx, index); |
| } |
| |
| TSError |
| TSCfgContextMoveEleDown(TSCfgContext ctx, int index) |
| { |
| return CfgContextMoveEleDown((CfgContext *) ctx, index); |
| } |
| |
| |
| TSError |
| TSCfgContextAppendEle(TSCfgContext ctx, TSCfgEle * ele) |
| { |
| return CfgContextAppendEle((CfgContext *) ctx, ele); |
| } |
| |
| TSError |
| TSCfgContextInsertEleAt(TSCfgContext ctx, TSCfgEle * ele, int index) |
| { |
| return CfgContextInsertEleAt((CfgContext *) ctx, ele, index); |
| } |
| |
| TSError |
| TSCfgContextRemoveEleAt(TSCfgContext ctx, int index) |
| { |
| return CfgContextRemoveEleAt((CfgContext *) ctx, index); |
| } |
| |
| TSError |
| TSCfgContextRemoveAll(TSCfgContext ctx) |
| { |
| return CfgContextRemoveAll((CfgContext *) ctx); |
| } |
| |
| /* checks if the fields in the ele are all valid */ |
| bool |
| TSIsValid(TSCfgEle * ele) |
| { |
| CfgEleObj *ele_obj; |
| |
| if (!ele) |
| return false; |
| |
| ele_obj = create_ele_obj_from_ele(ele); |
| return (ele_obj->isValid()); |
| } |
| |
| /* Network conifguration functions */ |
| |
| // close all file descriptors belong to process specified by pid |
| void |
| closeAllFds() |
| { |
| const int BUFFLEN = 200; |
| char command[BUFFLEN]; |
| char buffer[BUFFLEN]; // this is assumption.. so would break if some one try to hack this. |
| int num; |
| |
| // WARNING: this part of code doesn't work yet. for some strange reason, we can not upgrade |
| // to root |
| if (getuid() != 0) { // if not super user, need to upgrade to root |
| //printf("before upgrade:current uid%d, euid %d\n", getuid(), geteuid()); fflush(stdout); |
| if(seteuid(0) != 0 || setreuid(0, 0) != 0) |
| perror("[closeAllFds] unable to restore root privilege."); |
| //printf("after upgrade:current uid %d, euid %d\n", getuid(), geteuid()); fflush(stdout); |
| } |
| |
| if (getuid() == 0 || geteuid() == 0) { // only if it's successful |
| snprintf(command, sizeof(command), "/bin/ls -1 /proc/%" PRId64 "/fd", (int64_t)getpid()); |
| FILE *fd = popen(command, "r"); |
| if (fd) { |
| while (!feof(fd)) { |
| ATS_UNUSED_RETURN(fgets(buffer, BUFFLEN, fd)); |
| num = atoi(buffer); |
| if (num != fileno(fd) && num != 0 && num != 1 && num != 2) { // for out put |
| //printf("closing fd (%d)\n", num); fflush(stdout); |
| close(num); |
| } |
| } |
| pclose(fd); |
| } |
| } |
| } |
| |
| tsapi TSError rm_start_proxy() |
| { |
| |
| #if defined(linux) |
| static time_t rm_last_stop = 0; |
| |
| time_t time_diff = time(NULL) - rm_last_stop; |
| |
| if (time_diff > 60 || time_diff < 0) { // wrap around?? shall never happen |
| pid_t pid; |
| const char *argv[3]; |
| argv[0] = "net_config"; |
| argv[1] = "7"; |
| argv[2] = NULL; |
| char command_path[PATH_NAME_MAX + 1]; |
| Layout::relative_to(command_path, sizeof(command_path), |
| Layout::get()->bindir, "net_config"); |
| |
| rm_last_stop = time(NULL); |
| |
| if ((pid = fork()) < 0) { |
| exit(1); |
| } else if (pid > 0) { |
| // do not wait |
| } else { |
| closeAllFds(); |
| close(1); // close STDOUT |
| close(2); // close STDERR |
| |
| int res = execv(command_path, (char* const*)argv); |
| if (res != 0) { |
| perror("[rm_start_proxy] net_config stop_proxy failed! "); |
| } |
| _exit(res); |
| } |
| } // else already try to stop within 60s Window, skip |
| #endif |
| return TS_ERR_OKAY; |
| } |