00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include <records/I_RecCore.h>
00025 # include <records/I_RecHttp.h>
00026 # include <ts/ink_defs.h>
00027 # include <ts/Tokenizer.h>
00028 # include <strings.h>
00029
00030 SessionProtocolNameRegistry globalSessionProtocolNameRegistry;
00031
00032
00033
00034
00035
00036 const char * const TS_NPN_PROTOCOL_HTTP_0_9 = "http/0.9";
00037 const char * const TS_NPN_PROTOCOL_HTTP_1_0 = "http/1.0";
00038 const char * const TS_NPN_PROTOCOL_HTTP_1_1 = "http/1.1";
00039 const char * const TS_NPN_PROTOCOL_HTTP_2_0 = "h2-12";
00040 const char * const TS_NPN_PROTOCOL_SPDY_1 = "spdy/1";
00041 const char * const TS_NPN_PROTOCOL_SPDY_2 = "spdy/2";
00042 const char * const TS_NPN_PROTOCOL_SPDY_3 = "spdy/3";
00043 const char * const TS_NPN_PROTOCOL_SPDY_3_1 = "spdy/3.1";
00044
00045 const char * const TS_NPN_PROTOCOL_GROUP_HTTP = "http";
00046 const char * const TS_NPN_PROTOCOL_GROUP_HTTP2 = "http2";
00047 const char * const TS_NPN_PROTOCOL_GROUP_SPDY = "spdy";
00048
00049
00050 int TS_NPN_PROTOCOL_INDEX_HTTP_0_9 = SessionProtocolNameRegistry::INVALID;
00051 int TS_NPN_PROTOCOL_INDEX_HTTP_1_0 = SessionProtocolNameRegistry::INVALID;
00052 int TS_NPN_PROTOCOL_INDEX_HTTP_1_1 = SessionProtocolNameRegistry::INVALID;
00053 int TS_NPN_PROTOCOL_INDEX_HTTP_2_0 = SessionProtocolNameRegistry::INVALID;
00054 int TS_NPN_PROTOCOL_INDEX_SPDY_1 = SessionProtocolNameRegistry::INVALID;
00055 int TS_NPN_PROTOCOL_INDEX_SPDY_2 = SessionProtocolNameRegistry::INVALID;
00056 int TS_NPN_PROTOCOL_INDEX_SPDY_3 = SessionProtocolNameRegistry::INVALID;
00057 int TS_NPN_PROTOCOL_INDEX_SPDY_3_1 = SessionProtocolNameRegistry::INVALID;
00058
00059
00060 SessionProtocolSet HTTP_PROTOCOL_SET;
00061 SessionProtocolSet SPDY_PROTOCOL_SET;
00062 SessionProtocolSet HTTP2_PROTOCOL_SET;
00063 SessionProtocolSet DEFAULT_NON_TLS_SESSION_PROTOCOL_SET;
00064 SessionProtocolSet DEFAULT_TLS_SESSION_PROTOCOL_SET;
00065
00066 void RecHttpLoadIp(char const* value_name, IpAddr& ip4, IpAddr& ip6)
00067 {
00068 char value[1024];
00069 ip4.invalidate();
00070 ip6.invalidate();
00071 if (REC_ERR_OKAY == RecGetRecordString(value_name, value, sizeof(value))) {
00072 Tokenizer tokens(", ");
00073 int n_addrs = tokens.Initialize(value);
00074 for (int i = 0 ; i < n_addrs ; ++i ) {
00075 char const* host = tokens[i];
00076 IpEndpoint tmp4, tmp6;
00077
00078
00079 if (0 == ats_ip_getbestaddrinfo(host, &tmp4, &tmp6)) {
00080 if (ats_is_ip4(&tmp4)) {
00081 if (!ip4.isValid()) ip4 = tmp4;
00082 else Warning("'%s' specifies more than one IPv4 address, ignoring %s.", value_name, host);
00083 }
00084 if (ats_is_ip6(&tmp6)) {
00085 if (!ip6.isValid()) ip6 = tmp6;
00086 else Warning("'%s' specifies more than one IPv6 address, ignoring %s.", value_name, host);
00087 }
00088 } else {
00089 Warning("'%s' has an value '%s' that is not recognized as an IP address, ignored.", value_name, host);
00090 }
00091 }
00092 }
00093 }
00094
00095
00096 char const* const HttpProxyPort::DEFAULT_VALUE = "8080";
00097
00098 char const* const HttpProxyPort::PORTS_CONFIG_NAME = "proxy.config.http.server_ports";
00099
00100
00101
00102
00103
00104 char const* const HttpProxyPort::OPT_FD_PREFIX = "fd";
00105 char const* const HttpProxyPort::OPT_OUTBOUND_IP_PREFIX = "ip-out";
00106 char const* const HttpProxyPort::OPT_INBOUND_IP_PREFIX = "ip-in";
00107 char const* const HttpProxyPort::OPT_HOST_RES_PREFIX = "ip-resolve";
00108 char const* const HttpProxyPort::OPT_PROTO_PREFIX = "proto";
00109
00110 char const* const HttpProxyPort::OPT_IPV6 = "ipv6";
00111 char const* const HttpProxyPort::OPT_IPV4 = "ipv4";
00112 char const* const HttpProxyPort::OPT_TRANSPARENT_INBOUND = "tr-in";
00113 char const* const HttpProxyPort::OPT_TRANSPARENT_OUTBOUND = "tr-out";
00114 char const* const HttpProxyPort::OPT_TRANSPARENT_FULL = "tr-full";
00115 char const* const HttpProxyPort::OPT_TRANSPARENT_PASSTHROUGH = "tr-pass";
00116 char const* const HttpProxyPort::OPT_SSL = "ssl";
00117 char const* const HttpProxyPort::OPT_PLUGIN = "plugin";
00118 char const* const HttpProxyPort::OPT_BLIND_TUNNEL = "blind";
00119 char const* const HttpProxyPort::OPT_COMPRESSED = "compressed";
00120
00121
00122 namespace {
00123
00124 size_t const OPT_FD_PREFIX_LEN = strlen(HttpProxyPort::OPT_FD_PREFIX);
00125 size_t const OPT_OUTBOUND_IP_PREFIX_LEN = strlen(HttpProxyPort::OPT_OUTBOUND_IP_PREFIX);
00126 size_t const OPT_INBOUND_IP_PREFIX_LEN = strlen(HttpProxyPort::OPT_INBOUND_IP_PREFIX);
00127 size_t const OPT_HOST_RES_PREFIX_LEN = strlen(HttpProxyPort::OPT_HOST_RES_PREFIX);
00128 size_t const OPT_PROTO_PREFIX_LEN = strlen(HttpProxyPort::OPT_PROTO_PREFIX);
00129 }
00130
00131 namespace {
00132
00133
00134
00135
00136
00137 HttpProxyPort::Group GLOBAL_DATA;
00138 }
00139 HttpProxyPort::Group& HttpProxyPort::m_global = GLOBAL_DATA;
00140
00141 HttpProxyPort::HttpProxyPort()
00142 : m_fd(ts::NO_FD)
00143 , m_type(TRANSPORT_DEFAULT)
00144 , m_port(0)
00145 , m_family(AF_INET)
00146 , m_inbound_transparent_p(false)
00147 , m_outbound_transparent_p(false)
00148 , m_transparent_passthrough(false)
00149 {
00150 memcpy(m_host_res_preference, host_res_default_preference_order, sizeof(m_host_res_preference));
00151 }
00152
00153 bool HttpProxyPort::hasSSL(Group const& ports) {
00154 bool zret = false;
00155 for ( int i = 0 , n = ports.length() ; i < n && !zret ; ++i ) {
00156 if (ports[i].isSSL()) zret = true;
00157 }
00158 return zret;
00159 }
00160
00161 HttpProxyPort* HttpProxyPort::findHttp(Group const& ports, uint16_t family) {
00162 bool check_family_p = ats_is_ip(family);
00163 self* zret = 0;
00164 for ( int i = 0 , n = ports.length() ; i < n && !zret ; ++i ) {
00165 HttpProxyPort& p = ports[i];
00166 if (p.m_port &&
00167 TRANSPORT_DEFAULT == p.m_type &&
00168 ( !check_family_p || p.m_family == family)
00169 )
00170 zret = &p;;
00171 }
00172 return zret;
00173 }
00174
00175 char const*
00176 HttpProxyPort::checkPrefix(char const* src, char const* prefix, size_t prefix_len) {
00177 char const* zret = 0;
00178 if (0 == strncasecmp(prefix, src, prefix_len)) {
00179 src += prefix_len;
00180 if ('-' == *src || '=' == *src) ++src;
00181 zret = src;
00182 }
00183 return zret;
00184 }
00185
00186 bool
00187 HttpProxyPort::loadConfig(Vec<self>& entries) {
00188 char* text;
00189 bool found_p;
00190
00191 text = REC_readString(PORTS_CONFIG_NAME, &found_p);
00192 if (found_p) self::loadValue(entries, text);
00193 ats_free(text);
00194
00195 return 0 < entries.length();
00196 }
00197
00198 bool
00199 HttpProxyPort::loadDefaultIfEmpty(Group& ports) {
00200 if (0 == ports.length())
00201 self::loadValue(ports, DEFAULT_VALUE);
00202
00203 return 0 < ports.length();
00204 }
00205
00206 bool
00207 HttpProxyPort::loadValue(Vec<self>& ports, char const* text) {
00208 unsigned old_port_length = ports.length();
00209 if (text && *text) {
00210 Tokenizer tokens(", ");
00211 int n_ports = tokens.Initialize(text);
00212 if (n_ports > 0) {
00213 for ( int p = 0 ; p < n_ports ; ++p ) {
00214 char const* elt = tokens[p];
00215 HttpProxyPort entry;
00216 if (entry.processOptions(elt)) ports.push_back(entry);
00217 else Warning("No valid definition was found in proxy port configuration element '%s'", elt);
00218 }
00219 }
00220 }
00221 return ports.length() > old_port_length;
00222 }
00223
00224 bool
00225 HttpProxyPort::processOptions(char const* opts) {
00226 bool zret = false;
00227 bool af_set_p = false;
00228 bool host_res_set_p = false;
00229 bool sp_set_p = false;
00230 bool bracket_p = false;
00231 char const* value;
00232 IpAddr ip;
00233 Vec<char*> values;
00234
00235
00236 size_t opts_len = strlen(opts) + 1;
00237 char* text = static_cast<char*>(alloca(opts_len));
00238 memcpy(text, opts, opts_len);
00239
00240
00241 char* token = 0;
00242 for (char* spot = text ; *spot ; ++spot ) {
00243 if (bracket_p) {
00244 if (']' == *spot) bracket_p = false;
00245 } else if (':' == *spot) {
00246 *spot = 0;
00247 token = 0;
00248 } else {
00249 if (! token) {
00250 token = spot;
00251 values.push_back(token);
00252 }
00253 if ('[' == *spot) bracket_p = true;
00254 }
00255 }
00256 if (bracket_p) {
00257 Warning("Invalid port descriptor '%s' - left bracket without closing right bracket", opts);
00258 return zret;
00259 }
00260
00261 for ( int i = 0, n_items = values.length() ; i < n_items ; ++i) {
00262 char const* item = values[i];
00263 if (isdigit(item[0])) {
00264 char* ptr;
00265 int port = strtoul(item, &ptr, 10);
00266 if (ptr == item) {
00267
00268 Warning("Mangled port value '%s' in port configuration '%s'", item, opts);
00269 } else if (port <= 0 || 65536 <= port) {
00270 Warning("Port value '%s' out of range (1..65535) in port configuration '%s'", item, opts);
00271 } else {
00272 m_port = port;
00273 zret = true;
00274 }
00275 } else if (0 != (value = this->checkPrefix(item, OPT_FD_PREFIX, OPT_FD_PREFIX_LEN))) {
00276 char* ptr;
00277 int fd = strtoul(value, &ptr, 10);
00278 if (ptr == value) {
00279 Warning("Mangled file descriptor value '%s' in port descriptor '%s'", item, opts);
00280 } else {
00281 m_fd = fd;
00282 zret = true;
00283 }
00284 } else if (0 != (value = this->checkPrefix(item, OPT_INBOUND_IP_PREFIX, OPT_INBOUND_IP_PREFIX_LEN))) {
00285 if (0 == ip.load(value))
00286 m_inbound_ip = ip;
00287 else
00288 Warning("Invalid IP address value '%s' in port descriptor '%s'",
00289 item, opts
00290 );
00291 } else if (0 != (value = this->checkPrefix(item, OPT_OUTBOUND_IP_PREFIX, OPT_OUTBOUND_IP_PREFIX_LEN))) {
00292 if (0 == ip.load(value))
00293 this->outboundIp(ip.family()) = ip;
00294 else
00295 Warning("Invalid IP address value '%s' in port descriptor '%s'", item, opts);
00296 } else if (0 == strcasecmp(OPT_COMPRESSED, item)) {
00297 m_type = TRANSPORT_COMPRESSED;
00298 } else if (0 == strcasecmp(OPT_BLIND_TUNNEL, item)) {
00299 m_type = TRANSPORT_BLIND_TUNNEL;
00300 } else if (0 == strcasecmp(OPT_IPV6, item)) {
00301 m_family = AF_INET6;
00302 af_set_p = true;
00303 } else if (0 == strcasecmp(OPT_IPV4, item)) {
00304 m_family = AF_INET;
00305 af_set_p = true;
00306 } else if (0 == strcasecmp(OPT_SSL, item)) {
00307 m_type = TRANSPORT_SSL;
00308 } else if (0 == strcasecmp(OPT_PLUGIN, item)) {
00309 m_type = TRANSPORT_PLUGIN;
00310 } else if (0 == strcasecmp(OPT_TRANSPARENT_INBOUND, item)) {
00311 # if TS_USE_TPROXY
00312 m_inbound_transparent_p = true;
00313 # else
00314 Warning("Transparency requested [%s] in port descriptor '%s' but TPROXY was not configured.", item, opts);
00315 # endif
00316 } else if (0 == strcasecmp(OPT_TRANSPARENT_OUTBOUND, item)) {
00317 # if TS_USE_TPROXY
00318 m_outbound_transparent_p = true;
00319 # else
00320 Warning("Transparency requested [%s] in port descriptor '%s' but TPROXY was not configured.", item, opts);
00321 # endif
00322 } else if (0 == strcasecmp(OPT_TRANSPARENT_FULL, item)) {
00323 # if TS_USE_TPROXY
00324 m_inbound_transparent_p = true;
00325 m_outbound_transparent_p = true;
00326 # else
00327 Warning("Transparency requested [%s] in port descriptor '%s' but TPROXY was not configured.", item, opts);
00328 # endif
00329 } else if (0 == strcasecmp(OPT_TRANSPARENT_PASSTHROUGH, item)) {
00330 # if TS_USE_TPROXY
00331 m_transparent_passthrough = true;
00332 # else
00333 Warning("Transparent pass-through requested [%s] in port descriptor '%s' but TPROXY was not configured.", item, opts);
00334 # endif
00335 } else if (0 != (value = this->checkPrefix(item, OPT_HOST_RES_PREFIX, OPT_HOST_RES_PREFIX_LEN))) {
00336 this->processFamilyPreference(value);
00337 host_res_set_p = true;
00338 } else if (0 != (value = this->checkPrefix(item, OPT_PROTO_PREFIX, OPT_PROTO_PREFIX_LEN))) {
00339 this->processSessionProtocolPreference(value);
00340 sp_set_p = true;
00341 } else {
00342 Warning("Invalid option '%s' in proxy port configuration '%s'", item, opts);
00343 }
00344 }
00345
00346 bool in_ip_set_p = m_inbound_ip.isValid();
00347
00348 if (af_set_p) {
00349 if (in_ip_set_p && m_family != m_inbound_ip.family()) {
00350 Warning("Invalid port descriptor '%s' - the inbound adddress family [%s] is not the same type as the explicit family value [%s]",
00351 opts, ats_ip_family_name(m_inbound_ip.family()), ats_ip_family_name(m_family));
00352 zret = false;
00353 }
00354 } else if (in_ip_set_p) {
00355 m_family = m_inbound_ip.family();
00356 }
00357
00358
00359 if (m_outbound_transparent_p) {
00360 if (host_res_set_p &&
00361 (m_host_res_preference[0] != HOST_RES_PREFER_CLIENT ||
00362 m_host_res_preference[1] != HOST_RES_PREFER_NONE
00363 )) {
00364 Warning("Outbound transparent port '%s' requires the IP address resolution ordering '%s,%s'. "
00365 "This is set automatically and does not need to be set explicitly."
00366 , opts
00367 , HOST_RES_PREFERENCE_STRING[HOST_RES_PREFER_CLIENT]
00368 , HOST_RES_PREFERENCE_STRING[HOST_RES_PREFER_NONE]
00369 );
00370 }
00371 m_host_res_preference[0] = HOST_RES_PREFER_CLIENT;
00372 m_host_res_preference[1] = HOST_RES_PREFER_NONE;
00373 }
00374
00375
00376 if (m_transparent_passthrough && !m_inbound_transparent_p) {
00377 Warning("Port descriptor '%s' has transparent pass-through enabled without inbound transparency, this will be ignored.", opts);
00378 m_transparent_passthrough = false;
00379 }
00380
00381
00382 if (!sp_set_p)
00383 m_session_protocol_preference = this->isSSL()
00384 ? DEFAULT_TLS_SESSION_PROTOCOL_SET
00385 : DEFAULT_NON_TLS_SESSION_PROTOCOL_SET
00386 ;
00387
00388 return zret;
00389 }
00390
00391 void
00392 HttpProxyPort::processFamilyPreference(char const* value) {
00393 parse_host_res_preference(value, m_host_res_preference);
00394 }
00395
00396 void
00397 HttpProxyPort::processSessionProtocolPreference(char const* value) {
00398 m_session_protocol_preference.markAllOut();
00399 globalSessionProtocolNameRegistry.markIn(value, m_session_protocol_preference);
00400 }
00401
00402 void
00403 SessionProtocolNameRegistry::markIn(char const* value, SessionProtocolSet& sp_set) {
00404 int n;
00405 Tokenizer tokens(" ;|,:");
00406
00407 n = tokens.Initialize(value);
00408
00409 for ( int i = 0 ; i < n ; ++i ) {
00410 char const* elt = tokens[i];
00411
00412
00413 if (0 == strcasecmp(elt, TS_NPN_PROTOCOL_GROUP_HTTP)) {
00414 sp_set.markIn(HTTP_PROTOCOL_SET);
00415 } else if (0 == strcasecmp(elt, TS_NPN_PROTOCOL_GROUP_SPDY)) {
00416 sp_set.markIn(SPDY_PROTOCOL_SET);
00417 } else if (0 == strcasecmp(elt, TS_NPN_PROTOCOL_GROUP_HTTP2)) {
00418 sp_set.markIn(HTTP2_PROTOCOL_SET);
00419 } else {
00420 int idx = globalSessionProtocolNameRegistry.toIndex(elt);
00421 sp_set.markIn(idx);
00422 }
00423 }
00424 }
00425
00426 int
00427 HttpProxyPort::print(char* out, size_t n) {
00428 size_t zret = 0;
00429 ip_text_buffer ipb;
00430 bool need_colon_p = false;
00431
00432 if (m_inbound_ip.isValid()) {
00433 zret += snprintf(out+zret, n-zret, "%s=[%s]",
00434 OPT_INBOUND_IP_PREFIX,
00435 m_inbound_ip.toString(ipb, sizeof(ipb))
00436 );
00437 need_colon_p = true;
00438 }
00439 if (zret >= n) return n;
00440
00441 if (m_outbound_ip4.isValid()) {
00442 if (need_colon_p) out[zret++] = ':';
00443 zret += snprintf(out+zret, n-zret, "%s=[%s]",
00444 OPT_OUTBOUND_IP_PREFIX,
00445 m_outbound_ip4.toString(ipb, sizeof(ipb))
00446 );
00447 need_colon_p = true;
00448 }
00449 if (zret >= n) return n;
00450
00451 if (m_outbound_ip6.isValid()) {
00452 if (need_colon_p) out[zret++] = ':';
00453 zret += snprintf(out+zret, n-zret, "%s=[%s]",
00454 OPT_OUTBOUND_IP_PREFIX,
00455 m_outbound_ip6.toString(ipb, sizeof(ipb))
00456 );
00457 need_colon_p = true;
00458 }
00459 if (zret >= n) return n;
00460
00461 if (0 != m_port) {
00462 if (need_colon_p) out[zret++] = ':';
00463 zret += snprintf(out+zret, n-zret, "%d", m_port);
00464 need_colon_p = true;
00465 }
00466 if (zret >= n) return n;
00467
00468 if (ts::NO_FD != m_fd) {
00469 if (need_colon_p) out[zret++] = ':';
00470 zret += snprintf(out+zret, n-zret, "fd=%d", m_fd);
00471 }
00472 if (zret >= n) return n;
00473
00474
00475
00476
00477 if (AF_INET6 == m_family)
00478 zret += snprintf(out+zret, n-zret, ":%s", OPT_IPV6);
00479 if (zret >= n) return n;
00480
00481 if (TRANSPORT_BLIND_TUNNEL == m_type)
00482 zret += snprintf(out+zret, n-zret, ":%s", OPT_BLIND_TUNNEL);
00483 else if (TRANSPORT_SSL == m_type)
00484 zret += snprintf(out+zret, n-zret, ":%s", OPT_SSL);
00485 else if (TRANSPORT_PLUGIN == m_type)
00486 zret += snprintf(out+zret, n-zret, ":%s", OPT_PLUGIN);
00487 else if (TRANSPORT_COMPRESSED == m_type)
00488 zret += snprintf(out+zret, n-zret, ":%s", OPT_COMPRESSED);
00489 if (zret >= n) return n;
00490
00491 if (m_outbound_transparent_p && m_inbound_transparent_p)
00492 zret += snprintf(out+zret, n-zret, ":%s", OPT_TRANSPARENT_FULL);
00493 else if (m_inbound_transparent_p)
00494 zret += snprintf(out+zret, n-zret, ":%s", OPT_TRANSPARENT_INBOUND);
00495 else if (m_outbound_transparent_p)
00496 zret += snprintf(out+zret, n-zret, ":%s", OPT_TRANSPARENT_OUTBOUND);
00497
00498 if (m_transparent_passthrough)
00499 zret += snprintf(out+zret, n-zret, ":%s", OPT_TRANSPARENT_PASSTHROUGH);
00500
00501
00502
00503
00504
00505 if (!m_outbound_transparent_p &&
00506 0 != memcmp(m_host_res_preference, host_res_default_preference_order, sizeof(m_host_res_preference))) {
00507 zret += snprintf(out+zret, n-zret, ":%s=", OPT_HOST_RES_PREFIX);
00508 zret += ts_host_res_order_to_string(m_host_res_preference, out+zret, n-zret);
00509 }
00510
00511
00512
00513 SessionProtocolSet sp_set = m_session_protocol_preference;
00514 need_colon_p = true;
00515 if (sp_set == DEFAULT_NON_TLS_SESSION_PROTOCOL_SET && !this->isSSL()) {
00516 sp_set.markOut(DEFAULT_NON_TLS_SESSION_PROTOCOL_SET);
00517 } else if (sp_set == DEFAULT_TLS_SESSION_PROTOCOL_SET && this->isSSL()) {
00518 sp_set.markOut(DEFAULT_TLS_SESSION_PROTOCOL_SET);
00519 }
00520
00521
00522 if (sp_set.contains(HTTP_PROTOCOL_SET)) {
00523 zret += snprintf(out+zret, n-zret, ":%s=%s", OPT_PROTO_PREFIX,TS_NPN_PROTOCOL_GROUP_HTTP);
00524 sp_set.markOut(HTTP_PROTOCOL_SET);
00525 need_colon_p = false;
00526 }
00527 if (sp_set.contains(SPDY_PROTOCOL_SET)) {
00528 if (need_colon_p)
00529 zret += snprintf(out+zret, n-zret, ":%s=", OPT_PROTO_PREFIX);
00530 else
00531 out[zret++] = ';';
00532 zret += snprintf(out+zret, n-zret, TS_NPN_PROTOCOL_GROUP_SPDY);
00533 sp_set.markOut(SPDY_PROTOCOL_SET);
00534 need_colon_p = false;
00535 }
00536 if (sp_set.contains(HTTP2_PROTOCOL_SET)) {
00537 if (need_colon_p)
00538 zret += snprintf(out+zret, n-zret, ":%s=", OPT_PROTO_PREFIX);
00539 else
00540 out[zret++] = ';';
00541 zret += snprintf(out+zret, n-zret, "%s", TS_NPN_PROTOCOL_GROUP_HTTP2);
00542 sp_set.markOut(HTTP2_PROTOCOL_SET);
00543 need_colon_p = false;
00544 }
00545
00546 if (!sp_set.isEmpty()) {
00547 if (need_colon_p)
00548 zret += snprintf(out+zret, n-zret, ":%s=", OPT_PROTO_PREFIX);
00549 bool sep_p = !need_colon_p;
00550 for ( int k = 0 ; k < SessionProtocolSet::MAX ; ++k ) {
00551 if (sp_set.contains(k)) {
00552 zret += snprintf(out+zret, n-zret, "%s%s", sep_p ? ";" : "", globalSessionProtocolNameRegistry.nameFor(k));
00553 sep_p = true;
00554 }
00555 }
00556 }
00557
00558 return min(zret,n);
00559 }
00560
00561 void
00562 ts_host_res_global_init()
00563 {
00564
00565 memcpy(host_res_default_preference_order,
00566 HOST_RES_DEFAULT_PREFERENCE_ORDER,
00567 sizeof(host_res_default_preference_order));
00568
00569 char* ip_resolve = REC_ConfigReadString("proxy.config.hostdb.ip_resolve");
00570 if (ip_resolve) {
00571 parse_host_res_preference(ip_resolve, host_res_default_preference_order);
00572 }
00573 ats_free(ip_resolve);
00574 }
00575
00576
00577 void
00578 ts_session_protocol_well_known_name_indices_init()
00579 {
00580
00581 TS_NPN_PROTOCOL_INDEX_HTTP_0_9 = globalSessionProtocolNameRegistry.toIndexConst(TS_NPN_PROTOCOL_HTTP_0_9);
00582 TS_NPN_PROTOCOL_INDEX_HTTP_1_0 = globalSessionProtocolNameRegistry.toIndexConst(TS_NPN_PROTOCOL_HTTP_1_0);
00583 TS_NPN_PROTOCOL_INDEX_HTTP_1_1 = globalSessionProtocolNameRegistry.toIndexConst(TS_NPN_PROTOCOL_HTTP_1_1);
00584 TS_NPN_PROTOCOL_INDEX_HTTP_2_0 = globalSessionProtocolNameRegistry.toIndexConst(TS_NPN_PROTOCOL_HTTP_2_0);
00585 TS_NPN_PROTOCOL_INDEX_SPDY_1 = globalSessionProtocolNameRegistry.toIndexConst(TS_NPN_PROTOCOL_SPDY_1);
00586 TS_NPN_PROTOCOL_INDEX_SPDY_2 = globalSessionProtocolNameRegistry.toIndexConst(TS_NPN_PROTOCOL_SPDY_2);
00587 TS_NPN_PROTOCOL_INDEX_SPDY_3 = globalSessionProtocolNameRegistry.toIndexConst(TS_NPN_PROTOCOL_SPDY_3);
00588 TS_NPN_PROTOCOL_INDEX_SPDY_3_1 = globalSessionProtocolNameRegistry.toIndexConst(TS_NPN_PROTOCOL_SPDY_3_1);
00589
00590
00591 HTTP_PROTOCOL_SET.markIn(TS_NPN_PROTOCOL_INDEX_HTTP_0_9);
00592 HTTP_PROTOCOL_SET.markIn(TS_NPN_PROTOCOL_INDEX_HTTP_1_0);
00593 HTTP_PROTOCOL_SET.markIn(TS_NPN_PROTOCOL_INDEX_HTTP_1_1);
00594 HTTP2_PROTOCOL_SET.markIn(TS_NPN_PROTOCOL_INDEX_HTTP_2_0);
00595 SPDY_PROTOCOL_SET.markIn(TS_NPN_PROTOCOL_INDEX_SPDY_3);
00596 SPDY_PROTOCOL_SET.markIn(TS_NPN_PROTOCOL_INDEX_SPDY_3_1);
00597
00598 DEFAULT_TLS_SESSION_PROTOCOL_SET.markAllIn();
00599 DEFAULT_NON_TLS_SESSION_PROTOCOL_SET = HTTP_PROTOCOL_SET;
00600 }
00601
00602 SessionProtocolNameRegistry::SessionProtocolNameRegistry()
00603 : m_n(0)
00604 {
00605 memset(m_names, 0, sizeof(m_names));
00606 memset(&m_flags, 0, sizeof(m_flags));
00607 }
00608
00609 SessionProtocolNameRegistry::~SessionProtocolNameRegistry() {
00610 for ( size_t i = 0 ; i < m_n ; ++i ) {
00611 if (m_flags[i] & F_ALLOCATED)
00612 ats_free(const_cast<char*>(m_names[i]));
00613 }
00614 }
00615
00616 int
00617 SessionProtocolNameRegistry::toIndex(char const* name) {
00618 int zret = this->indexFor(name);
00619 if (INVALID == zret) {
00620 if (m_n < static_cast<size_t>(MAX)) {
00621 m_names[m_n] = ats_strdup(name);
00622 m_flags[m_n] = F_ALLOCATED;
00623 zret = m_n++;
00624 } else {
00625 ink_release_assert(!"Session protocol name registry overflow");
00626 }
00627 }
00628 return zret;
00629 }
00630
00631 int
00632 SessionProtocolNameRegistry::toIndexConst(char const* name) {
00633 int zret = this->indexFor(name);
00634 if (INVALID == zret) {
00635 if ( m_n < static_cast<size_t>(MAX)) {
00636 m_names[m_n] = name;
00637 zret = m_n++;
00638 } else {
00639 ink_release_assert(!"Session protocol name registry overflow");
00640 }
00641 }
00642 return zret;
00643 }
00644
00645 int
00646 SessionProtocolNameRegistry::indexFor(char const* name) const {
00647 for ( size_t i = 0 ; i < m_n ; ++i ) {
00648 if (0 == strcasecmp(name, m_names[i]))
00649 return i;
00650 }
00651 return INVALID;
00652 }
00653
00654 char const*
00655 SessionProtocolNameRegistry::nameFor(int idx) const {
00656 return 0 <= idx && idx < static_cast<int>(m_n)
00657 ? m_names[idx]
00658 : 0
00659 ;
00660 }