blob: ffd2036b75b5b2e141b9f198f16b070ac092e2d1 [file] [log] [blame]
/** @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.
*/
#include "P_Net.h"
#include "Main.h"
#include "Error.h"
#include "HttpConfig.h"
#include "HttpAccept.h"
#include "ReverseProxy.h"
#include "HttpSessionManager.h"
#include "HttpUpdateSM.h"
#include "HttpClientSession.h"
#include "HttpPages.h"
#include "HttpTunnel.h"
#include "Tokenizer.h"
#ifdef USE_NCA
#include "HttpNcaClient.h"
#endif
HttpPortEntry *http_port_attr_array = NULL;
HttpOtherPortEntry *http_other_port_array = NULL;
#ifdef DEBUG
extern "C"
{
void http_dump();
}
///////////////////////////////////////////////////////////
//
// http_dump()
//
///////////////////////////////////////////////////////////
void
http_dump()
{
// if (diags->on("http_dump"))
{
// httpNetProcessor.dump();
// HttpStateMachine::dump_state_machines();
}
return;
}
#endif
struct DumpStats:Continuation
{
int mainEvent(int event, void *e)
{
(void) event;
(void) e;
/* http_dump() */
// dump_stats();
return EVENT_CONT;
}
DumpStats():Continuation(NULL)
{
SET_HANDLER(&DumpStats::mainEvent);
}
};
HttpPortTypes
get_connection_attributes(char *attr)
{
HttpPortTypes attributes = SERVER_PORT_DEFAULT;
if (attr) {
if (strlen(attr) > 1) {
Warning("too many port attributes: '%s'", attr);
} else {
switch (*attr) {
case 'C':
attributes = SERVER_PORT_COMPRESSED;
break;
case 'X':
attributes = SERVER_PORT_DEFAULT;
break;
case 'T':
attributes = SERVER_PORT_BLIND_TUNNEL;
break;
default:
Warning("unknown port attribute '%s'", attr);
break;
}
}
}
return attributes;
}
static HttpOtherPortEntry *
parse_http_server_other_ports()
{
int list_entries;
int accept_index = 0;
int port = 0;
char *other_ports_str = NULL;
char *cur_entry;
char *attr_str;
Tokenizer listTok(", ");
HttpOtherPortEntry *additional_ports_array;
other_ports_str = HTTP_ConfigReadString("proxy.config.http.server_other_ports");
if (!other_ports_str || *other_ports_str == '\0') {
return NULL;
}
list_entries = listTok.Initialize(other_ports_str, SHARE_TOKS);
if (list_entries > 0) {
additional_ports_array = new HttpOtherPortEntry[list_entries + 1];
additional_ports_array[0].port = -1;
} else {
return NULL;
}
for (int i = 0; i < list_entries; i++) {
cur_entry = (char *) listTok[i];
// Check to see if there is a port attribute
attr_str = strchr(cur_entry, ':');
if (attr_str != NULL) {
*attr_str = '\0';
attr_str = attr_str + 1;
}
// Port value
// coverity[secure_coding]
// sscanf of token from tokenizer
if (sscanf(cur_entry, "%d", &port) != 1) {
Warning("failed to read accept port, discarding");
continue;
}
additional_ports_array[accept_index].port = port;
additional_ports_array[accept_index].type = get_connection_attributes(attr_str);
accept_index++;
}
ink_assert(accept_index < list_entries + 1);
additional_ports_array[accept_index].port = -1;
return additional_ports_array;
}
HttpAccept *plugin_http_accept = NULL;
/////////////////////////////////////////////////////////////////
//
// main()
//
/////////////////////////////////////////////////////////////////
void
init_HttpProxyServer(void)
{
#ifndef INK_NO_REVERSE
init_reverse_proxy();
#endif
HttpConfig::startup();
httpSessionManager.init();
http_pages_init();
ink_mutex_init(&debug_sm_list_mutex, "HttpSM Debug List");
ink_mutex_init(&debug_cs_list_mutex, "HttpCS Debug List");
// DI's request to disable/reenable ICP on the fly
icp_dynamic_enabled = 1;
// INKqa11918
init_max_chunk_buf();
#ifndef INK_NO_API
// Used to give plugins the ability to create http requests
// The equivalent of the connecting to localhost on the proxy
// port but without going through the operating system
//
if (plugin_http_accept == NULL) {
plugin_http_accept = NEW(new HttpAccept(SERVER_PORT_DEFAULT, false));
plugin_http_accept->mutex = new_ProxyMutex();
}
#endif
}
void
start_HttpProxyServer(int fd, int port, int ssl_fd)
{
char *dump_every_str = 0;
static bool called_once = false;
////////////////////////////////
// check if accept port is in //
// network safe range. //
////////////////////////////////
if ((port<1) || (port> 65535)) {
ProcessFatal("accept port %d is not between 1 and 65535 ", "please check configuration", port);
return;
}
if ((dump_every_str = getenv("PROXY_DUMP_STATS")) != 0) {
int dump_every_sec = atoi(dump_every_str);
eventProcessor.schedule_every(NEW(new DumpStats), HRTIME_SECONDS(dump_every_sec), ET_CALL);
}
/*
char * state_machines_max_count = NULL;
if ((state_machines_max_count =
getenv("HTTP_STATE_MACHINE_MAX_COUNT")) != 0)
{
HttpStateMachine::m_state_machines_max_count =
atoi(state_machines_max_count);
HTTP_ASSERT (HttpStateMachine::m_state_machines_max_count >= 1);
}
*/
///////////////////////////////////
// start accepting connections //
///////////////////////////////////
int sock_recv_buffer_size_in = 0;
int sock_send_buffer_size_in = 0;
unsigned long sock_option_flag_in = 0;
char *attr_string = 0;
static HttpPortTypes attr = SERVER_PORT_DEFAULT;
if (!called_once) {
// function can be called several times : do memory allocation once
REC_ReadConfigStringAlloc(attr_string, "proxy.config.http.server_port_attr");
REC_ReadConfigInteger(sock_recv_buffer_size_in, "proxy.config.net.sock_recv_buffer_size_in");
REC_ReadConfigInteger(sock_send_buffer_size_in, "proxy.config.net.sock_send_buffer_size_in");
REC_ReadConfigInteger(sock_option_flag_in, "proxy.config.net.sock_option_flag_in");
// deprecated configuration options - bcall 4/25/07
// these should be removed in the future
if (sock_recv_buffer_size_in == 0 && sock_send_buffer_size_in == 0 && sock_option_flag_in == 0) {
REC_ReadConfigInteger(sock_recv_buffer_size_in, "proxy.config.net.sock_recv_buffer_size");
REC_ReadConfigInteger(sock_send_buffer_size_in, "proxy.config.net.sock_send_buffer_size");
REC_ReadConfigInteger(sock_option_flag_in, "proxy.config.net.sock_option_flag");
}
// end of deprecated config options
if (attr_string) {
attr = get_connection_attributes(attr_string);
xfree(attr_string);
}
called_once = true;
if (http_port_attr_array) {
for (int i = 0; http_port_attr_array[i].fd != NO_FD; i++) {
HttpPortEntry & e = http_port_attr_array[i];
if (e.fd)
netProcessor.main_accept(NEW(new HttpAccept(e.type)), e.fd, 0, NULL, NULL, false,
sock_recv_buffer_size_in, sock_send_buffer_size_in, sock_option_flag_in);
}
} else {
// If traffic_server wasn't started with -A, get the list
// of other ports directly.
http_other_port_array = parse_http_server_other_ports();
}
}
if (!http_port_attr_array) {
netProcessor.main_accept(NEW(new HttpAccept(attr)), fd, port, NULL, NULL, false,
sock_recv_buffer_size_in, sock_send_buffer_size_in, sock_option_flag_in);
if (http_other_port_array) {
for (int i = 0; http_other_port_array[i].port != -1; i++) {
HttpOtherPortEntry & e = http_other_port_array[i];
if ((e.port<1) || (e.port> 65535))
Warning("additional port out of range ignored: %d", e.port);
else
netProcessor.main_accept(NEW(new HttpAccept(e.type)), fd, e.port, NULL, NULL, false,
sock_recv_buffer_size_in, sock_send_buffer_size_in, sock_option_flag_in);
}
}
} else {
for (int i = 0; http_port_attr_array[i].fd != NO_FD; i++) {
HttpPortEntry & e = http_port_attr_array[i];
if (!e.fd) {
netProcessor.main_accept(NEW(new HttpAccept(attr)), fd, port, NULL, NULL, false,
sock_recv_buffer_size_in, sock_send_buffer_size_in, sock_option_flag_in);
}
}
}
#ifdef HAVE_LIBSSL
SslConfigParams *sslParam = sslTerminationConfig.acquire();
if (sslParam->getTerminationMode() & sslParam->SSL_TERM_MODE_CLIENT)
sslNetProcessor.main_accept(NEW(new HttpAccept(SERVER_PORT_SSL)), ssl_fd, sslParam->getAcceptPort());
sslTerminationConfig.release(sslParam);
#endif
#ifdef USE_NCA
start_NcaServer();
#endif
#ifdef DEBUG
if (diags->on("http_dump")) {
// HttpStateMachine::dump_state_machines();
}
#endif
#ifndef INK_NO_TESTS
if (is_action_tag_set("http_update_test")) {
init_http_update_test();
}
#endif
}
void
start_HttpProxyServerBackDoor(int port)
{
netProcessor.main_accept(NEW(new HttpAccept(SERVER_PORT_DEFAULT, true)), NO_FD, port);
}