2 * @file virtualservice_tcp.cpp
3 * @brief VirtualService class implementations for TCP
5 * L7VSD: Linux Virtual Server for Layer7 Load Balancing
6 * Copyright (C) 2009 NTT COMWARE Corporation.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 **********************************************************************/
27 #include <boost/date_time/posix_time/posix_time.hpp>
28 #include <boost/bind.hpp>
29 #include <boost/lexical_cast.hpp>
30 #include <boost/format.hpp>
31 #include <sys/socket.h>
32 #include <linux/version.h>
35 #include "virtualservice.h"
36 #include "logger_enum.h"
38 #include "parameter.h"
39 #include "snmpagent.h"
41 #include "logger_access_manager.h"
43 // implementation for virtualservice_tcp
45 * virtualservice_tcp class constructor.
47 l7vs::virtualservice_tcp::virtualservice_tcp(const l7vsd &invsd,
48 const replication &inrep,
49 const virtualservice_element &inelement)
51 virtualservice_base(invsd, inrep, inelement)
53 access_log_file_name = "";
54 dispatcher.reset(new boost::asio::io_service(10));
55 calc_bps_timer.reset(new boost::asio::deadline_timer(*dispatcher));
56 replication_timer.reset(new boost::asio::deadline_timer(*dispatcher));
57 protomod_rep_timer.reset(new boost::asio::deadline_timer(*dispatcher));
58 schedmod_rep_timer.reset(new boost::asio::deadline_timer(*dispatcher));
59 acceptor_.reset(new boost::asio::ip::tcp::acceptor(*dispatcher));
60 sslcontext.reset(new boost::asio::ssl::context(*dispatcher, DEFAULT_SSL_METHOD));
67 private_key_file = "";
68 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
69 private_key_passwd_dir = "";
70 private_key_passwd_file = "";
72 verify_cert_depth = 0;
74 is_tmp_dh_use = false;
78 is_session_cache_use = false;
79 session_cache_mode = 0;
80 session_cache_size = 0;
81 session_cache_timeout = 0;
82 handshake_timeout = 0;
85 * virtualservice_tcp class destructor.
87 l7vs::virtualservice_tcp::~virtualservice_tcp()
91 * replication interrupt event
96 void l7vs::virtualservice_tcp::handle_replication_interrupt(const boost::system::error_code &err)
98 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
99 boost::format fmt("in_function: void virtualservice_tcp::handle_replication_interrupt( "
100 "const boost::system::error_code& err ): err = %s, err.message = %s");
101 fmt % (err ? "true" : "false") % err.message();
102 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 20, fmt.str(), __FILE__, __LINE__);
107 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, err.message(), __FILE__, __LINE__);
111 interrupt_running_flag++;
114 replication &rep_noconst = const_cast<replication &>(rep);
116 if (replication::REPLICATION_SINGLE == rep_noconst.get_status()) {
117 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "replication mode is single.",
119 interrupt_running_flag--;
123 std::stringstream tmp_tcp_ep;
124 tmp_tcp_ep << element.tcp_accept_endpoint;
125 std::stringstream tmp_udp_ep;
126 tmp_udp_ep << element.udp_recv_endpoint;
127 std::stringstream tmp_sorry_ep;
128 tmp_sorry_ep << element.sorry_endpoint;
130 //get replication area
131 unsigned int rep_size = 0;
132 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
133 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
134 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
135 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, REP_BLOCK_SIZE_ERR_MSG,
137 interrupt_running_flag--;
141 //check max data size
142 if ((rep_size * DATA_SIZE) <
143 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
144 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, REP_AREA_SIZE_ERR_MSG,
146 interrupt_running_flag--;
150 //lock replication area
151 rep_noconst.lock(REP_AREA_NAME);
153 //read header value and set loop count
154 unsigned int loop_cnt = rep_header_ptr->data_num;
155 //if data_num over MAX_REPLICATION_DATA_NUM, data_num = 0
156 if (static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt) {
160 //set start pointer(pointer of replication_data)
161 replication_data *rep_data_ptr = reinterpret_cast<replication_data *>(++rep_header_ptr);
164 for (unsigned int i = 0; i < loop_cnt; ++i) {
165 //check equal udpmode and tcp_accept_endpoint
166 if ((rep_data_ptr->udpmode == element.udpmode) &&
167 (0 == strncmp(rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 47))) {
171 //increment data pointer
175 //if it is new data, increment data num.
177 rep_header_ptr = reinterpret_cast<replication_header *>(
178 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
179 ++(rep_header_ptr->data_num);
181 //write replication data
182 rep_data_ptr->udpmode = element.udpmode;
183 strncpy(rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 48);
184 strncpy(rep_data_ptr->udp_endpoint, tmp_udp_ep.str().c_str(), 48);
185 rep_data_ptr->sorry_maxconnection = element.sorry_maxconnection;
186 strncpy(rep_data_ptr->sorry_endpoint, tmp_sorry_ep.str().c_str(), 48);
187 rep_data_ptr->sorry_flag = element.sorry_flag;
188 rep_data_ptr->sorry_fwdmode = element.sorry_fwdmode;
189 rep_data_ptr->qos_up = element.qos_upstream;
190 rep_data_ptr->qos_down = element.qos_downstream;
192 //unlock replication area
193 rep_noconst.unlock(REP_AREA_NAME);
195 if (0 == virtualservice_stop_flag.get()) {
196 //register handle_replication_interrupt
197 replication_timer->expires_from_now(
198 boost::posix_time::milliseconds(param_data.rep_interval));
199 replication_timer->async_wait(boost::bind(
200 &virtualservice_tcp::handle_replication_interrupt,
201 this, boost::asio::placeholders::error));
203 interrupt_running_flag--;
205 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
206 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
207 "out_function: void virtualservice_tcp::handle_replication_interrupt( "
208 "const boost::system::error_code& err )", __FILE__, __LINE__);
213 * read replication data
215 * @param read_replicationdata
219 void l7vs::virtualservice_tcp::read_replicationdata()
221 Logger funclog(LOG_CAT_L7VSD_VIRTUALSERVICE, 22, "function: "
222 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
224 replication &rep_noconst = const_cast<replication &>(rep);
226 if (replication::REPLICATION_SINGLE == rep_noconst.get_status()) {
227 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, "replication mode is single.",
232 unsigned int rep_size = 0;
233 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
234 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
235 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
236 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 3, REP_BLOCK_SIZE_ERR_MSG,
238 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
239 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 23, "out_function: "
240 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
245 //check max data size
246 if ((rep_size * DATA_SIZE) <
247 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
248 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 4, REP_AREA_SIZE_ERR_MSG,
250 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
251 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 24, "out_function: "
252 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
256 //lock replication area
257 rep_noconst.lock(REP_AREA_NAME);
259 //read header value and set loop count
260 unsigned int loop_cnt = rep_header_ptr->data_num;
261 //if data_num over MAX_REPLICATION_DATA_NUM, set data_num = 0
262 if (static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt) {
263 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 5, REP_BLOCK_SIZE_ERR_MSG,
265 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
266 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 25, "out_function: "
267 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
269 rep_header_ptr->data_num = 0;
270 rep_noconst.unlock(REP_AREA_NAME);
274 //set start pointer(pointer of replication_data)
275 replication_data *rep_data_ptr = reinterpret_cast<replication_data *>(++rep_header_ptr);
278 for (unsigned int i = 0; i < loop_cnt; ++i) {
279 //get tcp endpoint data
280 std::string tmpstr = rep_data_ptr->tcp_endpoint;
282 unsigned short portno;
284 portno = boost::lexical_cast<unsigned short>(tmpstr.substr((tmpstr.rfind(":") + 1)));
285 } catch (const boost::bad_lexical_cast &err) {
288 if (tmpstr[0] == '[') {
290 ipaddr = tmpstr.substr(1, (tmpstr.rfind("]") - 1));
293 ipaddr = tmpstr.substr(0, tmpstr.rfind(":"));
295 //check equal udpmode and tcp_accept_endpoint
296 if ((rep_data_ptr->udpmode == element.udpmode) &&
297 (tcp_endpoint_type(boost::asio::ip::address::from_string(ipaddr), portno)
298 == element.tcp_accept_endpoint)) {
299 element.sorry_maxconnection = rep_data_ptr->sorry_maxconnection;
300 tmpstr = rep_data_ptr->sorry_endpoint;
302 portno = boost::lexical_cast<unsigned short>(
303 tmpstr.substr((tmpstr.rfind(":") + 1)));
304 } catch (const boost::bad_lexical_cast &err) {
307 if (tmpstr[0] == '[') {
309 ipaddr = tmpstr.substr(1, (tmpstr.rfind("]") - 1));
312 ipaddr = tmpstr.substr(0, tmpstr.rfind(":"));
314 element.sorry_endpoint =
315 tcp_endpoint_type(boost::asio::ip::address::from_string(ipaddr), portno);
316 element.sorry_flag = rep_data_ptr->sorry_flag;
317 element.sorry_fwdmode = (virtualservice_element::SORRYSERVER_FWDMODE_TAG)(rep_data_ptr->sorry_fwdmode);
318 element.qos_upstream = rep_data_ptr->qos_up;
319 element.qos_downstream = rep_data_ptr->qos_down;
322 //increment data pointer
326 //unlock replication area
327 rep_noconst.unlock(REP_AREA_NAME);
329 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
330 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 26, "out_function: "
331 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
338 * @param handle_accept
342 void l7vs::virtualservice_tcp::handle_accept(const l7vs::session_thread_control *stc_ptr, const boost::system::error_code &err)
344 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
345 boost::format fmt("in_function: void virtualservice_tcp::handle_accept( "
346 "const boost::shared_ptr<session_thread_control> , "
347 "const boost::system::error_code& err ): err = %s, err.message = %s");
348 fmt % (err ? "true" : "false") % err.message();
349 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 27, fmt.str(), __FILE__, __LINE__);
352 if (unlikely(virtualservice_stop_flag.get())) {
357 boost::mutex::scoped_lock lock(adm_cmd_wait_flag_mutex);
358 if (unlikely(adm_cmd_wait_flag)){
359 adm_cmd_wait_flag_cond.wait(lock);
363 session_thread_control *stc_ptr_noconst = const_cast<session_thread_control *>(stc_ptr);
365 if (unlikely(err == boost::asio::error::operation_aborted)) { // nomal exit case
366 boost::format fmt("Thread ID[%d] handle accept cancel : %s");
367 fmt % boost::this_thread::get_id() % err.message();
368 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 0, fmt.str(), __FILE__, __LINE__);
370 } else if (unlikely(err)) { // register next accept handle when error mode.
371 if (!ssl_virtualservice_mode_flag) {
372 waiting_session->get_client_socket().get_socket().close();
373 acceptor_->async_accept(waiting_session->get_client_socket().get_socket(),
374 boost::bind(&virtualservice_tcp::handle_accept,
377 boost::asio::placeholders::error));
379 waiting_session->get_client_ssl_socket().lowest_layer().close();
380 acceptor_->async_accept(waiting_session->get_client_ssl_socket().lowest_layer(),
381 boost::bind(&virtualservice_tcp::handle_accept,
384 boost::asio::placeholders::error));
386 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, err.message(), __FILE__, __LINE__);
390 tcp_session *tmp_session = stc_ptr_noconst->get_session().get();
392 if (ssl_file_name != "") {
394 //*-------- DEBUG LOG --------*/
395 if (unlikely(LOG_LV_DEBUG ==
396 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
397 std::stringstream buf;
398 buf << "virtualservice_tcp::handle_accept(): ";
399 buf << "ssl session cache flush before: ";
400 get_ssl_session_cache_info(buf);
401 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
405 //*------ DEBUG LOG END ------*/
407 // ssl session cache flush
408 if (is_session_cache_use == true) {
409 long ssl_cache_num = SSL_CTX_sess_number(sslcontext->impl());
410 if (ssl_cache_num >= session_cache_size) {
415 //*-------- DEBUG LOG --------*/
416 if (unlikely(LOG_LV_DEBUG ==
417 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
418 std::stringstream buf;
419 buf << "virtualservice_tcp::handle_accept(): ";
420 buf << "ssl session cache flush after: ";
421 get_ssl_session_cache_info(buf);
422 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
426 //*------ DEBUG LOG END ------*/
429 // initialize session
430 stc_ptr_noconst->get_session()->initialize();
432 // send access log output ON or OFF message to tcp_session
433 stc_ptr_noconst->session_access_log_output_mode_change(access_log_flag);
435 active_sessions.insert(tmp_session, stc_ptr_noconst);
438 //check sorry flag and status
440 (0 != element.sorry_flag) ||
441 ((0 < element.sorry_maxconnection) && ((active_count.get() >= static_cast<size_t>(element.sorry_maxconnection)))
444 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
445 boost::format fmt("Connection switch Sorry mode. "
446 "active_session.size = %d, active_count.get = %d");
447 fmt % active_sessions.size() % active_count.get();
448 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 30, fmt.str(), __FILE__, __LINE__);
451 stc_ptr_noconst->get_session()->set_virtual_service_message(tcp_session::SORRY_STATE_ENABLE, boost::asio::ip::tcp::endpoint());
454 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
455 boost::format fmt1("active session thread id = %d");
456 fmt1 % stc_ptr_noconst->get_upthread_id();
457 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 31, fmt1.str(), __FILE__, __LINE__);
458 boost::format fmt2("pool_session.size = %d");
459 fmt2 % pool_sessions.size();
460 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 32, fmt2.str(), __FILE__, __LINE__);
461 boost::format fmt3("active_session.size = %d");
462 fmt3 % active_sessions.size();
463 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 33, fmt3.str(), __FILE__, __LINE__);
464 boost::format fmt4("active_count = %d");
465 fmt4 % active_count.get();
466 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 34, fmt4.str(), __FILE__, __LINE__);
469 stc_ptr_noconst->startupstream();
470 stc_ptr_noconst->startdownstream();
472 //left session is less than the threshold
473 if ((sessionpool_alert_flag == false) &&
474 ((pool_sessions.size() + 1) < param_data.session_pool_alert_on)) {
475 //create trap message
476 trapmessage trap_msg;
477 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
478 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
480 //push the trap message
481 snmpagent::push_trapmessage(trap_msg, err_code);
483 std::string str("Push trap message failed :");
484 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 38, str , __FILE__, __LINE__);
486 //set sessionpool alert flag true
487 sessionpool_alert_flag = true;
490 //waiting, pool_sessions.size become over 1
491 //pick up session from pool
492 session_thread_control *stc_ptr_register_accept;
495 stc_ptr_register_accept = pool_sessions.pop();
496 if (stc_ptr_register_accept) break;
497 else if (pool_sessions.empty()) dispatcher->poll();
498 timespec ts = { 0, 50 };
499 nanosleep(&ts, NULL);
502 //session add wait_sessions
503 boost::mutex::scoped_lock up_wait_lk(stc_ptr_register_accept->get_upthread_mutex());
504 boost::mutex::scoped_lock down_wait_lk(stc_ptr_register_accept->get_downthread_mutex());
506 waiting_session = stc_ptr_register_accept->get_session().get();
507 waiting_stc = stc_ptr_register_accept;
509 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
510 boost::format fmt1("active session thread id = %d");
511 fmt1 % stc_ptr_register_accept->get_upthread_id();
512 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 35, fmt1.str(), __FILE__, __LINE__);
513 boost::format fmt2("pool_session.size = %d");
514 fmt2 % pool_sessions.size();
515 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 36, fmt2.str(), __FILE__, __LINE__);
516 boost::format fmt3("active_session.size = %d");
517 fmt3 % active_sessions.size();
518 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 37, fmt3.str(), __FILE__, __LINE__);
519 boost::format fmt4("active_count = %d");
520 fmt4 % active_count.get();
521 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 38, fmt4.str(), __FILE__, __LINE__);
524 //register accept event handler
525 if (!ssl_virtualservice_mode_flag) {
526 acceptor_->async_accept(waiting_session->get_client_socket().get_socket(),
527 boost::bind(&virtualservice_tcp::handle_accept,
529 stc_ptr_register_accept,
530 boost::asio::placeholders::error));
532 acceptor_->async_accept(waiting_session->get_client_ssl_socket().lowest_layer(),
533 boost::bind(&virtualservice_tcp::handle_accept,
535 stc_ptr_register_accept,
536 boost::asio::placeholders::error));
539 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
540 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 39,
542 "void virtualservice_tcp::handle_accept( "
543 "const boost::shared_ptr<session_thread_control> , "
544 "const boost::system::error_code& err )", __FILE__, __LINE__);
549 * initialize virtualservice(TCP)
554 void l7vs::virtualservice_tcp::initialize(l7vs::error_code &err)
558 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
559 boost::format formatter("in_function: void virtualservice_tcp::initialize( "
560 "l7vs::error_code& err )");
561 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, formatter.str(), __FILE__, __LINE__);
563 if (pool_sessions.size() != 0) {
564 err.setter(true, "VirtualService already initialized.");
565 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
566 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
567 "l7vs::error_code& err ): err = %s, err.message = %s");
568 formatter % (err ? "true" : "false") % err.get_message();
569 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 41, formatter.str(),
575 //load parameter value
578 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
579 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
580 "l7vs::error_code& err ): err = %s, err.message = %s");
581 formatter % (err ? "true" : "false") % err.get_message();
582 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 42, formatter.str(),
588 // access log flag and access log file name setting contents check.
589 if (element.access_log_flag == 1 && element.access_log_file_name == "") {
590 boost::format formatter("access log file name not set error");
591 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 3, formatter.str(), __FILE__, __LINE__);
592 err.setter(true, "access log file name not set error");
596 logger_implement_access *access_log_instance = NULL;
597 // access log instance create.
598 if (element.access_log_file_name != "") {
600 = logger_access_manager::getInstance().find_logger_implement_access(
601 element.access_log_file_name,
602 element.access_log_rotate_arguments,
604 if (access_log_instance == NULL) {
605 boost::format formatter("access logger Instance acquisition err = %s, "
606 "err.message = %s ");
607 formatter % (err ? "true" : "false") % err.get_message();
608 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 4, formatter.str(),
610 err.setter(true, "access log class instance create failed");
616 boost::asio::ip::address address = element.tcp_accept_endpoint.address();
617 #ifdef SCHED_SETAFFINITY
618 vsnic_cpumask = get_cpu_mask(address);
619 rsnic_cpumask = get_cpu_mask(param_data.nic_realserver_side);
623 boost::system::error_code acceptor_err;
624 acceptor_->open(element.tcp_accept_endpoint.protocol(), acceptor_err);
626 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 5, acceptor_err.message(),
628 err.setter(true, acceptor_err.message());
631 acceptor_->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), acceptor_err);
633 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 6, acceptor_err.message(),
635 err.setter(true, acceptor_err.message());
638 if (likely(address.is_v6())) {
639 boost::asio::ip::v6_only option(true);
640 acceptor_->set_option(option, acceptor_err);
642 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 7, acceptor_err.message(),
644 err.setter(true, acceptor_err.message());
648 acceptor_->bind(element.tcp_accept_endpoint, acceptor_err);
650 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 8, acceptor_err.message(),
652 err.setter(true, acceptor_err.message());
656 //read replication data
657 read_replicationdata();
659 //load protocol module
660 protomod = protocol_module_control::getInstance().load_module(element.protocol_module_name);
661 if (NULL == protomod) {
663 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 9, PROTOMOD_LOAD_ERROR_MSG,
665 err.setter(true, PROTOMOD_LOAD_ERROR_MSG);
666 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
667 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
668 "l7vs::error_code& err ): err = %s, err.message = %s");
669 formatter % (err ? "true" : "false") % err.get_message();
670 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 43, formatter.str(),
675 //Protocol Module Initialize
676 protomod->init_logger_functions(
677 boost::bind(&Logger::getLogLevel, LOG_CAT_PROTOCOL),
678 boost::bind(&Logger::putLogFatal, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
679 boost::bind(&Logger::putLogError, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
680 boost::bind(&Logger::putLogWarn, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
681 boost::bind(&Logger::putLogInfo, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
682 boost::bind(&Logger::putLogDebug, LOG_CAT_PROTOCOL, _1, _2, _3, _4));
683 protomod->initialize(
684 boost::bind(&virtualservice_tcp::rs_list_begin, this),
685 boost::bind(&virtualservice_tcp::rs_list_end, this),
686 boost::bind(&virtualservice_tcp::rs_list_next, this, _1),
687 boost::bind(&virtualservice_tcp::rs_list_lock, this),
688 boost::bind(&virtualservice_tcp::rs_list_unlock, this));
689 protomod->init_replication_functions(
690 boost::bind(&virtualservice_tcp::replication_pay_memory, this, _1, _2),
691 boost::bind(&virtualservice_tcp::replication_area_lock, this, element.protocol_module_name),
692 boost::bind(&virtualservice_tcp::replication_area_unlock, this, element.protocol_module_name),
693 element.tcp_accept_endpoint,
694 element.udp_recv_endpoint);
695 tcp_schedule_func_type sched_rs_func = boost::bind(
696 &virtualservice_tcp::schedule_rs, this, _1, _2, _3, _4, _5);
697 protomod->register_schedule(sched_rs_func);
699 protocol_module_base::check_message_result pm_result;
701 pm_result = protomod->check_parameter(element.protocol_args);
702 if (!pm_result.flag) {
703 err.setter(true, "Protocol Module argument error.");
704 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
705 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
706 "l7vs::error_code& err ): err = %s, err.message = %s");
707 formatter % (err ? "true" : "false") % err.get_message();
708 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 44, formatter.str(),
713 pm_result = protomod->set_parameter(element.protocol_args);
714 if (!pm_result.flag) {
715 err.setter(true, "Protocol Module argument error.");
716 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
717 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
718 "l7vs::error_code& err ): err = %s, err.message = %s");
719 formatter % (err ? "true" : "false") % err.get_message();
720 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 45, formatter.str(),
726 protomod->get_option_info(protocol_module_for_indication_options);
727 element.protocol_module_for_indication_options = protocol_module_for_indication_options;
729 //load schedule module
730 schedmod = schedule_module_control::getInstance().load_module(element.schedule_module_name);
731 if (NULL == schedmod) {
733 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 10, SCHEDMOD_LOAD_ERROR_MSG,
735 err.setter(true, SCHEDMOD_LOAD_ERROR_MSG);
736 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
737 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
738 "l7vs::error_code& err ) : err = %s, err.message = %s");
739 formatter % (err ? "true" : "false") % err.get_message();
740 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 46, formatter.str(),
745 //Schedule Module Initialize
746 schedmod->init_logger_functions(
747 boost::bind(&Logger::getLogLevel, LOG_CAT_SCHEDULE),
748 boost::bind(&Logger::putLogFatal, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
749 boost::bind(&Logger::putLogError, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
750 boost::bind(&Logger::putLogWarn, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
751 boost::bind(&Logger::putLogInfo, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
752 boost::bind(&Logger::putLogDebug, LOG_CAT_SCHEDULE, _1, _2, _3, _4));
753 schedmod->initialize();
754 schedmod->init_replication_functions(
755 boost::bind(&virtualservice_tcp::replication_pay_memory, this, _1, _2),
756 boost::bind(&virtualservice_tcp::replication_area_lock, this, element.schedule_module_name),
757 boost::bind(&virtualservice_tcp::replication_area_unlock, this, element.schedule_module_name),
758 element.tcp_accept_endpoint,
759 element.udp_recv_endpoint);
761 // access log flag set
762 access_log_flag = false;
763 if (element.access_log_flag == 1) {
764 access_log_flag = true;
767 // access log rotation information set.
768 if (element.access_log_rotate_key_info == "") {
769 element.access_log_rotate_key_info = "none";
770 element.access_log_rotate_verbose_info = logger_access_manager::getInstance().get_rotate_default_verbose_displayed_contents();
772 element.access_log_rotate_verbose_info = element.access_log_rotate_key_info;
774 access_log_file_name = element.access_log_file_name;
775 access_log_rotate_arguments = element.access_log_rotate_arguments;
778 ssl_virtualservice_mode_flag = false;
779 ssl_file_name = element.ssl_file_name;
780 if (ssl_file_name != "") {
781 ssl_file_name = element.ssl_file_name;
783 if (unlikely(!get_ssl_parameter())) {
785 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 11, "get ssl parameter failed",
787 err.setter(true, "get ssl parameter failed");
790 // set SSL configuration
791 if (unlikely(!set_ssl_config())) {
793 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 12, "set ssl config failed",
795 err.setter(true, "set ssl config failed");
798 ssl_virtualservice_mode_flag = true;
804 //create session pool
806 int session_pool_size;
807 if (element.session_thread_pool_size > 0) {
808 session_pool_size = element.session_thread_pool_size;
810 session_pool_size = param_data.session_pool_size;
812 for (int i = 0; i < session_pool_size; ++i) {
814 tcp_session *sess = new tcp_session(*this,
817 element.tcp_accept_endpoint,
818 ssl_virtualservice_mode_flag,
820 is_session_cache_use,
822 access_log_instance);
823 session_result_message result = sess->initialize();
824 if (result.flag == true) {
825 err.setter(result.flag, result.message);
826 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
827 boost::format formatter("out_function: "
828 "void virtualservice_tcp::initialize( "
829 "l7vs::error_code& err ): err = %s, "
831 formatter % (err ? "true" : "false") % err.get_message();
832 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 47,
833 formatter.str(), __FILE__, __LINE__);
837 session_thread_control *p_stc = new session_thread_control(
838 sess, vsnic_cpumask, rsnic_cpumask, -1);
840 ret = p_stc->start_thread();
843 } else if (ret == EPERM) {
845 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 999, "Not super user authority",
847 err.setter(true, "set pthread schedule parameter.");
850 while (!pool_sessions.push(p_stc)) {}
853 LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "error, create session.",
856 err.setter(true, "error, create session.");
859 l7vs::error_code finalize_err;
860 finalize_err.setter(false, "");
861 finalize(finalize_err);
863 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
864 boost::format formatter("out_function: "
865 "void virtualservice_tcp::initialize( "
866 "l7vs::error_code& err ): err = %s, err.message = %s");
867 formatter % (err ? "true" : "false") % err.get_message();
868 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 48, formatter.str(),
874 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
875 boost::format fmt1("pool_session.size = %d");
876 fmt1 % pool_sessions.size();
877 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 49, fmt1.str(),
879 boost::format fmt2("active_session.size = %d");
880 fmt2 % active_sessions.size();
881 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 50, fmt2.str(),
886 err.setter(false, "");
888 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
889 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
890 "l7vs::error_code& err ): err = %s, err.message = %s");
891 formatter % (err ? "true" : "false") % err.get_message();
892 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 51, formatter.str(),
898 * finalize virtualservice(TCP)
903 void l7vs::virtualservice_tcp::finalize(l7vs::error_code &err)
906 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
907 boost::format formatter("in_function: void virtualservice_tcp::finalize( "
908 "l7vs::error_code& err )");
909 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 52, formatter.str(),
911 boost::format fmt1("pool_session.size = %d");
912 fmt1 % pool_sessions.size();
913 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 53, fmt1.str(),
915 boost::format fmt2("active_session.size = %d");
916 fmt2 % active_sessions.size();
917 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 54, fmt2.str(),
921 //release sessions[i]->join();
922 while (!pool_sessions.empty()) {
923 session_thread_control *stc = pool_sessions.pop();
926 boost::mutex::scoped_lock upthread_wait(stc->get_upthread_mutex());
927 boost::mutex::scoped_lock downthread_wait(stc->get_downthread_mutex());
931 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
932 boost::format fmt("join pool session: pool_session.size = %d");
933 fmt % pool_sessions.size();
934 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 55, fmt.str(),
938 //release waiting session
943 //unload ProtocolModule
945 //finalize ProtocolModule
946 protomod->finalize();
947 //unload ProtocolModule
948 protocol_module_control::getInstance().unload_module(protomod);
951 //unload ScheduleModule
953 schedule_module_control::getInstance().unload_module(schedmod);
957 active_sessions.clear();
958 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
959 boost::format fmt1("pool_session.size = %d");
960 fmt1 % pool_sessions.size();
961 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 56, fmt1.str(), __FILE__, __LINE__);
962 boost::format fmt2("active_session.size = %d");
963 fmt2 % active_sessions.size();
964 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 57, fmt2.str(), __FILE__, __LINE__);
967 //clear replication_data
968 bool replication_status = true;
969 replication &rep_noconst = const_cast<replication &>(rep);
971 if (replication::REPLICATION_SINGLE != rep_noconst.get_status()) {
972 unsigned int rep_size = 0;
973 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
974 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
975 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
976 err.setter(true, REP_BLOCK_SIZE_ERR_MSG);
977 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 6, REP_BLOCK_SIZE_ERR_MSG,
979 replication_status = false;
982 //check max data size
983 if ((rep_size * DATA_SIZE) <
984 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
985 err.setter(true, REP_AREA_SIZE_ERR_MSG);
986 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 7, REP_AREA_SIZE_ERR_MSG,
988 replication_status = false;
990 if ((NULL != rep_header_ptr) && (replication_status)) {
991 //lock replication area
992 rep_noconst.lock(REP_AREA_NAME);
994 rep_header_ptr->data_num = 0;
995 //unlock replication area
996 rep_noconst.unlock(REP_AREA_NAME);
1000 //vsd.release_virtual_service( element );
1001 if (access_log_file_name != "") {
1002 // erase access log instance.
1003 logger_access_manager::getInstance().erase_logger_implement_access(access_log_file_name, err);
1004 if (unlikely(err)) {
1005 boost::format fmt("access logger instance erase err:%s");
1006 fmt % err.get_message();
1007 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 8,
1009 __FILE__, __LINE__);
1013 vsd.release_virtual_service(element);
1015 err.setter(false, "");
1017 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1018 boost::format formatter("out_function: void virtualservice_tcp::finalize( "
1019 "l7vs::error_code& err ): err = %s, err.message = %s");
1020 formatter % (err ? "true" : "false") % err.get_message();
1021 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 58, formatter.str(), __FILE__, __LINE__);
1027 * equal compare virtualservice(TCP)
1029 * @param virtualservice_base
1030 * @return bool ( true = equal )
1032 bool l7vs::virtualservice_tcp::operator==(const l7vs::virtualservice_base &in)
1034 boost::format formatter("function: void virtualservice_tcp::operator==( "
1035 "const l7vs::virtualservice_base& in )");
1036 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 59, formatter.str(), __FILE__, __LINE__);
1038 virtualservice_base &vs = const_cast<virtualservice_base &>(in);
1039 return ((element.tcp_accept_endpoint == vs.get_element().tcp_accept_endpoint)
1040 && (element.udpmode == vs.get_element().udpmode));
1044 * not-equal compare virtualservice(TCP)
1046 * @param virtualservice_base
1047 * @return bool ( true = not-equal )
1049 bool l7vs::virtualservice_tcp::operator!=(const l7vs::virtualservice_base &in)
1051 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1052 boost::format formatter("in/out_function: void virtualservice_tcp::operator!=( "
1053 "const l7vs::virtualservice_base& in )");
1054 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 60, formatter.str(), __FILE__, __LINE__);
1056 virtualservice_base &vs = const_cast<virtualservice_base &>(in);
1057 return ((element.tcp_accept_endpoint != vs.get_element().tcp_accept_endpoint)
1058 || (element.udpmode != vs.get_element().udpmode));
1062 * add VirtualService( not-implement )
1064 * @param virtualservice_element
1068 void l7vs::virtualservice_tcp::set_virtualservice(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1070 err.setter(false, "");
1074 * edit VirtualService
1076 * @param virtualservice_element
1080 void l7vs::virtualservice_tcp::edit_virtualservice(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1082 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1083 boost::format formatter("in_function: void virtualservice_tcp::edit_virtualservice( "
1084 "const l7vs::virtualservice_element& in,"
1085 "l7vs::error_code& err ): dump in ");
1086 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 61, formatter.str(), __FILE__, __LINE__);
1089 virtualservice_element &elem = const_cast<virtualservice_element &>(in);
1090 if ((element.udpmode != elem.udpmode) ||
1091 (element.tcp_accept_endpoint != elem.tcp_accept_endpoint) ||
1092 (element.protocol_module_name != elem.protocol_module_name)) {
1093 err.setter(true, "Virtual Service does not exist.");
1094 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1095 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1096 "const l7vs::virtualservice_element& in,"
1097 "l7vs::error_code& err ): err = %s, err.message = %s");
1098 formatter % (err ? "true" : "false") % err.get_message();
1099 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 62, formatter.str(),
1100 __FILE__, __LINE__);
1105 //if change ScheduleModule Name, unload old ScheduleModule and load new ScheduleModule
1106 if ((element.schedule_module_name != elem.schedule_module_name) && ("" != elem.schedule_module_name)) {
1107 schedule_module_control::getInstance().unload_module(schedmod);
1108 schedmod = schedule_module_control::getInstance().load_module(elem.schedule_module_name);
1109 if (NULL == schedmod) {
1111 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 13, SCHEDMOD_LOAD_ERROR_MSG,
1112 __FILE__, __LINE__);
1113 err.setter(true, SCHEDMOD_LOAD_ERROR_MSG);
1114 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1115 boost::format formatter("out_function: "
1116 "void virtualservice_tcp::edit_virtualservice( "
1117 "const l7vs::virtualservice_element& in,"
1118 "l7vs::error_code& err ): err = %s, err.message = %s");
1119 formatter % (err ? "true" : "false") % err.get_message();
1120 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 63, formatter.str(),
1121 __FILE__, __LINE__);
1125 element.schedule_module_name = elem.schedule_module_name;
1128 //additional PM options(for protomod_url)
1129 protocol_module_base::check_message_result result;
1130 if( NULL != protomod ){
1131 result = protomod->add_parameter( elem.protocol_args );
1133 for( size_t i = 0; i < elem.protocol_args.size(); ++i ){
1134 element.protocol_args.push_back( elem.protocol_args[i] );
1137 err.setter( true, result.message );
1138 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1139 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1140 "const l7vs::virtualservice_element& in,"
1141 "l7vs::error_code& err ): err = %s, err.message = %s");
1142 formatter % ( err ? "true" : "false") % err.get_message();
1143 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 64, formatter.str(),
1144 __FILE__, __LINE__ );
1150 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 14, PROTOMOD_LOAD_ERROR_MSG,
1151 __FILE__, __LINE__ );
1152 err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
1153 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1154 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1155 "const l7vs::virtualservice_element& in,"
1156 "l7vs::error_code& err ): err = %s, err.message = %s");
1157 formatter % ( err ? "true" : "false") % err.get_message();
1158 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 65, formatter.str(),
1159 __FILE__, __LINE__ );
1166 if (ULLONG_MAX == elem.qos_upstream) {
1167 element.qos_upstream = 0ULL;
1168 } else if (0ULL != elem.qos_upstream) {
1169 element.qos_upstream = elem.qos_upstream;
1172 if (ULLONG_MAX == elem.qos_downstream) {
1173 element.qos_downstream = 0ULL;
1174 } else if (0ULL != elem.qos_downstream) {
1175 element.qos_downstream = elem.qos_downstream;
1177 //sorry_maxconnection;
1178 if (LLONG_MAX == elem.sorry_maxconnection) {
1179 element.sorry_maxconnection = 0;
1180 } else if (0 != elem.sorry_maxconnection) {
1181 element.sorry_maxconnection = elem.sorry_maxconnection;
1184 if (INT_MAX == elem.sorry_flag) {
1185 element.sorry_flag = 0;
1186 } else if (0 != elem.sorry_flag) {
1187 element.sorry_flag = 1;
1190 if (virtualservice_element::FWD_NONE != elem.sorry_fwdmode) {
1191 element.sorry_fwdmode = elem.sorry_fwdmode;
1194 //if endpoint of SorryServer equal 255.255.255.255:0,not update
1195 //if equal endpoint 255.255.255.255:0, clear sorry parameters
1196 if (elem.sorry_endpoint ==
1197 boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("255.255.255.255"), (0))) {
1198 element.sorry_endpoint = boost::asio::ip::tcp::endpoint(
1199 boost::asio::ip::address::from_string("0.0.0.0"), (0));
1200 element.sorry_maxconnection = 0LL;
1201 element.sorry_flag = false;
1202 active_sessions.do_all(boost::bind(&session_thread_control::session_sorry_disable, _1));
1204 if (elem.sorry_endpoint != boost::asio::ip::tcp::endpoint(
1205 boost::asio::ip::address::from_string("0.0.0.0"), (0))) {
1206 element.sorry_endpoint = elem.sorry_endpoint;
1208 active_sessions.do_all(boost::bind(
1209 &session_thread_control::session_sorry_mode_change, _1, elem.sorry_flag));
1212 if (elem.access_log_flag != -1) {
1213 // access log flag ON and access log filename not set.
1214 if (elem.access_log_flag == 1 && element.access_log_file_name == "") {
1216 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 15, SCHEDMOD_LOAD_ERROR_MSG,
1217 __FILE__, __LINE__);
1218 err.setter(true, "access log flag change err.");
1222 // access log flag check and send access log output ON or OFF message to tcp_session
1223 element.access_log_flag = elem.access_log_flag;
1224 if (elem.access_log_flag == 1 && access_log_flag == false) {
1225 active_sessions.do_all(boost::bind(
1226 &session_thread_control::session_accesslog_output_mode_on, _1));
1227 access_log_flag = true;
1228 } else if (elem.access_log_flag == 0 && access_log_flag == true) {
1229 active_sessions.do_all(boost::bind(
1230 &session_thread_control::session_accesslog_output_mode_off, _1));
1231 access_log_flag = false;
1235 err.setter(false, "");
1237 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1238 boost::format formatter("out_function: void virtualservice_tcp::set_virtualservice( "
1239 "const l7vs::virtualservice_element& in,"
1240 "l7vs::error_code& err ): err = %s, err.message = %s");
1241 formatter % (err ? "true" : "false") % err.get_message();
1242 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 66, formatter.str(), __FILE__, __LINE__);
1249 * @param virtualservice_element
1253 void l7vs::virtualservice_tcp::add_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1255 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1256 boost::format formatter("in_function: void virtualservice_tcp::add_realserver( "
1257 "const l7vs::virtualservice_element& in,"
1258 "l7vs::error_code& err )");
1259 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 67, formatter.str(), __FILE__, __LINE__);
1262 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1264 //check equal virtualservice
1265 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1266 err.setter(true, "Virtual Service does not exist.");
1267 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1268 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1269 "const l7vs::virtualservice_element& in,"
1270 "l7vs::error_code& err ): err = %s, err.message = %s");
1271 formatter % (err ? "true" : "false") % err.get_message();
1272 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 68, formatter.str(),
1273 __FILE__, __LINE__);
1278 if (in.realserver_vector.size() == 0U) {
1279 err.setter(true, ".");
1280 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1281 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1282 "const l7vs::virtualservice_element& in,"
1283 "l7vs::error_code& err ): err = %s, err.message = %s");
1284 formatter % (err ? "true" : "false") % err.get_message();
1285 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 69, formatter.str(),
1286 __FILE__, __LINE__);
1290 //lock rs_list_ref_count_inc_mutex
1291 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1293 //waiting, rs_list_ref_count become 0
1294 while (rs_list_ref_count != 0ULL) {
1295 boost::this_thread::sleep(
1296 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1300 //check duplication realserver
1301 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1302 itr != in_element.realserver_vector.end();
1304 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1305 rs_itr != rs_list.end(); ++rs_itr) {
1306 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1307 err.setter(true, "Real Server already exist.");
1308 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1309 boost::format formatter("out_function: "
1310 "void virtualservice_tcp::add_realserver( "
1311 "const l7vs::virtualservice_element& in,"
1312 "l7vs::error_code& err ): err = %s, err.message = %s");
1313 formatter % (err ? "true" : "false") % err.get_message();
1314 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 70,
1315 formatter.str(), __FILE__, __LINE__);
1323 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1324 itr != in_element.realserver_vector.end();
1327 rs.tcp_endpoint = itr->tcp_endpoint;
1328 rs.udp_endpoint = itr->udp_endpoint;
1329 rs.weight = itr->weight;
1330 rs.fwdmode = itr->fwdmode;
1331 rs_list.push_back(rs);
1334 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1335 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1336 "const l7vs::virtualservice_element& in,"
1337 "l7vs::error_code& err ): err = %s, err.message = %s");
1338 formatter % (err ? "true" : "false") % err.get_message();
1339 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 71, formatter.str(), __FILE__, __LINE__);
1346 * @param virtualservice_element
1350 void l7vs::virtualservice_tcp::edit_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1352 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1353 boost::format formatter("in_function: void virtualservice_tcp::edit_realserver( "
1354 "const l7vs::virtualservice_element& in,"
1355 "l7vs::error_code& err )");
1356 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 72, formatter.str(), __FILE__, __LINE__);
1358 //check equal virtualservice
1359 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1360 err.setter(true, "Virtual Service does not exist.");
1361 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1362 boost::format formatter("out_function: void virtualservice_tcp::edit_realserver( "
1363 "const l7vs::virtualservice_element& in,"
1364 "l7vs::error_code& err ): err = %s, err.message = %s");
1365 formatter % (err ? "true" : "false") % err.get_message();
1366 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 73, formatter.str(),
1367 __FILE__, __LINE__);
1372 //lock rs_list_ref_count_inc_mutex
1373 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1375 //waiting, rs_list_ref_count become 0
1376 while (rs_list_ref_count != 0ULL) {
1377 boost::this_thread::sleep(
1378 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1382 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1384 //check is exist realserver
1385 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1386 itr != in_element.realserver_vector.end();
1388 bool exist_flag = false;
1389 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1390 rs_itr != rs_list.end(); ++rs_itr) {
1391 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1396 err.setter(true, "Real Server does not exist.");
1397 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1398 boost::format formatter("out_function: "
1399 "void virtualservice_tcp::edit_realserver( "
1400 "const l7vs::virtualservice_element& in,"
1401 "l7vs::error_code& err ): err = %s, err.message = %s");
1402 formatter % (err ? "true" : "false") % err.get_message();
1403 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 74, formatter.str(),
1404 __FILE__, __LINE__);
1410 //lock adm_cmd_wait_flag on
1411 adm_cmd_wait_flag_mutex.lock();
1412 adm_cmd_wait_flag = true;
1413 adm_cmd_wait_flag_cond.notify_one();
1414 adm_cmd_wait_flag_mutex.unlock();
1417 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1418 itr != in_element.realserver_vector.end();
1420 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1421 rs_itr != rs_list.end(); ++rs_itr) {
1422 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1423 rs_itr->udp_endpoint = itr->udp_endpoint;
1425 if (itr->weight != -1) {
1426 rs_itr->weight = itr->weight;
1428 if (itr->fwdmode != realserver_element::FWD_NONE) {
1429 rs_itr->fwdmode = itr->fwdmode;
1435 //lock adm_cmd_wait_flag off
1436 adm_cmd_wait_flag_mutex.lock();
1437 adm_cmd_wait_flag = false;
1438 adm_cmd_wait_flag_cond.notify_one();
1439 adm_cmd_wait_flag_mutex.unlock();
1441 err.setter(false, "");
1442 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1443 boost::format formatter("out_function: void virtualservice_tcp::edit_realserver( "
1444 "const l7vs::virtualservice_element& in,"
1445 "l7vs::error_code& err ): err = %s, err.message = %s");
1446 formatter % (err ? "true" : "false") % err.get_message();
1447 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 75, formatter.str(), __FILE__, __LINE__);
1454 * @param virtualservice_element
1458 void l7vs::virtualservice_tcp::del_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1460 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1461 boost::format formatter("in_function: void virtualservice_tcp::del_realserver( "
1462 "const l7vs::virtualservice_element& in,"
1463 "l7vs::error_code& err )");
1464 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 76, formatter.str(), __FILE__, __LINE__);
1467 //check equal virtualservice
1468 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1469 err.setter(true, "Virtual Service is not equal.");
1470 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1471 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1472 "const l7vs::virtualservice_element& in,"
1473 "l7vs::error_code& err ): err = %s, err.message = %s");
1474 formatter % (err ? "true" : "false") % err.get_message();
1475 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 77, formatter.str(),
1476 __FILE__, __LINE__);
1481 //lock rs_list_ref_count_inc_mutex
1482 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1484 //waiting, rs_list_ref_count become 0
1485 while (rs_list_ref_count != 0ULL) {
1486 boost::this_thread::sleep(
1487 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1491 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1493 //check is exist realserver
1494 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1495 itr != in_element.realserver_vector.end();
1497 bool exist_flag = false;
1498 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1499 rs_itr != rs_list.end(); ++rs_itr) {
1500 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1505 err.setter(true, "Real Server does not exist.");
1506 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1507 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1508 "const l7vs::virtualservice_element& in,"
1509 "l7vs::error_code& err ): err = %s, err.message = %s");
1510 formatter % (err ? "true" : "false") % err.get_message();
1511 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 78, formatter.str(),
1512 __FILE__, __LINE__);
1518 //lock adm_cmd_wait_flag on
1519 adm_cmd_wait_flag_mutex.lock();
1520 adm_cmd_wait_flag = true;
1521 adm_cmd_wait_flag_cond.notify_one();
1522 adm_cmd_wait_flag_mutex.unlock();
1525 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1526 itr != in_element.realserver_vector.end();
1528 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1529 rs_itr != rs_list.end(); ++rs_itr) {
1530 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1531 boost::asio::ip::tcp::endpoint del_endpoint = rs_itr->tcp_endpoint;
1532 rs_list.erase(rs_itr);
1533 active_sessions.do_all(boost::bind(&session_thread_control::session_realserver_remove, _1, del_endpoint));
1539 //lock adm_cmd_wait_flag off
1540 adm_cmd_wait_flag_mutex.lock();
1541 adm_cmd_wait_flag = false;
1542 adm_cmd_wait_flag_cond.notify_one();
1543 adm_cmd_wait_flag_mutex.unlock();
1545 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1546 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1547 "const l7vs::virtualservice_element& in,"
1548 "l7vs::error_code& err ): err = %s, err.message = %s");
1549 formatter % (err ? "true" : "false") % err.get_message();
1550 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 79, formatter.str(), __FILE__, __LINE__);
1555 * main loop of virtualservice(TCP)
1560 void l7vs::virtualservice_tcp::run()
1562 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function: void virtualservice_tcp::run()",
1563 __FILE__, __LINE__);
1565 if (pool_sessions.size() == 0) {
1566 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.",
1567 __FILE__, __LINE__);
1570 boost::asio::socket_base::receive_buffer_size option(8192 * 192);
1571 acceptor_->set_option(option);
1572 //set socket option TCP_DEFER_ACCEPT
1573 if (defer_accept_opt) {
1574 size_t len = sizeof(defer_accept_val);
1575 int err = ::setsockopt(acceptor_->native(), IPPROTO_TCP, TCP_DEFER_ACCEPT, &defer_accept_val, len);
1576 if (unlikely(err)) {
1578 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
1579 "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__);
1583 acceptor_->listen();
1585 //left session is less than the threshold
1586 if ((sessionpool_alert_flag == false) &&
1587 (pool_sessions.size() < param_data.session_pool_alert_on)) {
1588 //create trap message
1589 trapmessage trap_msg;
1590 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
1591 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
1592 error_code err_code;
1593 //push the trap message
1594 snmpagent::push_trapmessage(trap_msg, err_code);
1596 std::string msg("Push trap message failed.");
1597 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, msg, __FILE__, __LINE__);
1600 //set sessionpool alert flag true
1601 sessionpool_alert_flag = true;
1604 //switch active a session
1605 session_thread_control *stc_ptr;
1607 stc_ptr = pool_sessions.pop();
1610 waiting_session = stc_ptr->get_session().get();
1611 waiting_stc = stc_ptr;
1613 if (!ssl_virtualservice_mode_flag) {
1614 acceptor_->async_accept(waiting_session->get_client_socket().get_socket(),
1615 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1616 boost::asio::placeholders::error));
1618 acceptor_->async_accept(waiting_session->get_client_ssl_socket().lowest_layer(),
1619 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1620 boost::asio::placeholders::error));
1622 //register timer event handler
1623 calc_bps_timer->expires_from_now(boost::posix_time::milliseconds(param_data.bps_interval));
1624 calc_bps_timer->async_wait(boost::bind(&virtualservice_tcp::handle_throughput_update,
1625 this, boost::asio::placeholders::error));
1627 //register handle_replication_interrupt
1628 replication_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1629 replication_timer->async_wait(boost::bind(&virtualservice_tcp::handle_replication_interrupt,
1630 this, boost::asio::placeholders::error));
1631 //register handle_protomod_replication
1632 protomod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1633 protomod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_protomod_replication,
1634 this, boost::asio::placeholders::error));
1635 //register handle_schedmod_replication
1636 schedmod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1637 schedmod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_schedmod_replication,
1638 this, boost::asio::placeholders::error));
1640 //run dispatcher(start io_service loop)
1641 work.reset(new boost::asio::io_service::work(*dispatcher));
1642 boost::thread_group dispatcher_thread_group;
1644 for (int i = 0; i < IO_SERVICE_THREADS_NUM; i++) {
1645 dispatcher_thread_group.create_thread(boost::bind(&boost::asio::io_service::run, dispatcher));
1648 //join dispatcher_thread_group when virtualservice_tcp::stop() executed.
1649 dispatcher_thread_group.join_all();
1658 void l7vs::virtualservice_tcp::stop()
1660 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function: void virtualservice_tcp::stop()",
1661 __FILE__, __LINE__);
1663 boost::system::error_code err;
1664 virtualservice_stop_flag++;
1665 while (interrupt_running_flag.get()) {
1666 boost::this_thread::yield();
1669 acceptor_->close(err);
1671 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__);
1676 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1677 active_sessions.do_all(boost::bind(&session_thread_control::session_stop, _1));
1678 while (active_sessions.size()) {
1679 boost::this_thread::yield();
1683 calc_bps_timer->cancel();
1684 replication_timer->cancel();
1685 protomod_rep_timer->cancel();
1686 schedmod_rep_timer->cancel();
1689 dispatcher->reset();
1695 * increment active-connection count
1700 void l7vs::virtualservice_tcp::connection_active(const boost::asio::ip::tcp::endpoint &in)
1702 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1703 boost::format formatter("in_function: void virtualservice_tcp::connection_active( "
1704 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1706 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__);
1709 for (std::list<realserver>::iterator itr = rs_list.begin();
1710 itr != rs_list.end();
1712 if (itr->tcp_endpoint == in) {
1713 itr->increment_active();
1720 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1721 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 83, "out_function: "
1722 "void virtualservice_tcp::connection_active()", __FILE__, __LINE__);
1727 * increment in-active-connection (and decrement active-connection count)
1732 void l7vs::virtualservice_tcp::connection_inactive(const boost::asio::ip::tcp::endpoint &in)
1734 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1735 boost::format formatter("in_function: void virtualservice_tcp::connection_inactive( "
1736 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1738 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__);
1741 for (std::list<realserver>::iterator itr = rs_list.begin();
1742 itr != rs_list.end();
1744 if (itr->tcp_endpoint == in) {
1745 itr->decrement_active();
1746 itr->increment_inact();
1753 //left session is more than the release threshold
1754 if ((sessionpool_alert_flag == true) &&
1755 ((pool_sessions.size() + 1) > param_data.session_pool_alert_off)) {
1756 //create trap message
1757 trapmessage trap_msg;
1758 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_OFF;
1759 trap_msg.message = "TRAP00020012,Warning release: The left-session has exceeded the release threshold of left-session warning.";
1760 error_code err_code;
1761 //push the trap message
1762 snmpagent::push_trapmessage(trap_msg, err_code);
1764 std::string msg("Push trap message failed.");
1765 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 39, msg, __FILE__, __LINE__);
1768 //set sessionpool alert flag true
1769 sessionpool_alert_flag = false;
1772 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1773 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 85, "out_function: "
1774 "void virtualservice_tcp::connection_inactive()", __FILE__, __LINE__);
1784 void l7vs::virtualservice_tcp::release_session(const tcp_session *session_ptr)
1786 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1787 boost::format funclog_fmt("in_function: void virtualservice_tcp::release_session( "
1788 "const tcp_session* session_ptr ): session_ptr = %d");
1789 funclog_fmt % session_ptr;
1790 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 86, funclog_fmt.str(), __FILE__, __LINE__);
1793 session_thread_control *stc_ptr = active_sessions.find(session_ptr);
1794 if (unlikely(NULL == stc_ptr)) {
1795 boost::format fmt("session release fail: "
1796 "active_sessions.find( const tcp_session* session_ptr = %d )");
1798 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*XXX*/999, fmt.str(), __FILE__, __LINE__);
1799 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1800 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 88, "out_function: "
1801 "void virtualservice_tcp::release_session( "
1802 "const boost::thread::id thread_id )", __FILE__, __LINE__);
1807 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1808 boost::format fmt1("pool_session.size = %d");
1809 fmt1 % pool_sessions.size();
1810 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 89, fmt1.str(), __FILE__, __LINE__);
1811 boost::format fmt2("active_session.size = %d");
1812 fmt2 % active_sessions.size();
1813 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 90, fmt2.str(), __FILE__, __LINE__);
1814 boost::format fmt3("active_count = %d");
1815 fmt3 % active_count.get();
1816 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 91, fmt3.str(), __FILE__, __LINE__);
1818 active_sessions.erase(session_ptr);
1820 while (!pool_sessions.push(stc_ptr)) {}
1822 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1823 boost::format fmt1("pool_session.size = %d");
1824 fmt1 % pool_sessions.size();
1825 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 92, fmt1.str(), __FILE__, __LINE__);
1826 boost::format fmt2("active_session.size = %d");
1827 fmt2 % active_sessions.size();
1828 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 93, fmt2.str(), __FILE__, __LINE__);
1829 boost::format fmt3("active_count = %d");
1830 fmt3 % active_count.get();
1831 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 94, fmt3.str(), __FILE__, __LINE__);
1833 boost::format funclog_fmt("out_function: void virtualservice_tcp::release_session( "
1834 "const tcp_session* session_ptr ): session_ptr = %d");
1835 funclog_fmt % session_ptr;
1836 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 95, funclog_fmt.str(), __FILE__, __LINE__);
1841 // set_socket_option
1843 void l7vs::virtualservice_tcp::set_socket_option()
1846 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1847 boost::format funclog_fmt("in_function: void virtualservice_tcp::et_socket_option");
1848 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 96, funclog_fmt.str(), __FILE__, __LINE__);
1851 // socket option check & set
1852 //! TCP_DEFER_ACCEPT (false:not set,true:set option)
1853 defer_accept_opt = false;
1854 //! TCP_DEFER_ACCEPT option value
1855 defer_accept_val = 0;
1856 //! TCP_NODELAY (false:not set,true:set option)
1857 set_sock_opt.nodelay_opt = false;
1858 //! TCP_NODELAY option value (false:off,true:on)
1859 set_sock_opt.nodelay_val = false;
1860 //! TCP_CORK (false:not set,true:set option)
1861 set_sock_opt.cork_opt = false;
1862 //! TCP_CORK option value (false:off,true:on)
1863 set_sock_opt.cork_val = false;
1864 //! TCP_KEEPALIVE (false:not set,true:set option)
1865 set_sock_opt.keepalive_opt = false;
1866 //! TCP_KEEPALIVE option value (false:off,true:on)
1867 set_sock_opt.keepalive_val = false;
1868 //! TCP_QUICKACK (false:not set,true:set option)
1869 set_sock_opt.quickack_opt = false;
1870 //! TCP_QUICKACK option value (false:off,true:on)
1871 set_sock_opt.quickack_val = false;
1873 // set socket option
1874 if (element.socket_option_tcp_defer_accept != 0) {
1875 defer_accept_opt = true;
1876 if (element.socket_option_tcp_defer_accept == 1) {
1877 defer_accept_val = 1;
1881 if (element.socket_option_tcp_nodelay != 0) {
1882 set_sock_opt.nodelay_opt = true;
1883 if (element.socket_option_tcp_nodelay == 1) {
1884 set_sock_opt.nodelay_val = true;
1888 if (element.socket_option_tcp_cork != 0) {
1889 set_sock_opt.cork_opt = true;
1890 if (element.socket_option_tcp_cork == 1) {
1891 set_sock_opt.cork_val = true;
1895 if (element.socket_option_tcp_keepalive != 0) {
1896 set_sock_opt.keepalive_opt = true;
1897 if (element.socket_option_tcp_keepalive == 1) {
1898 set_sock_opt.keepalive_val = true;
1902 if (element.socket_option_tcp_quickack != 0) {
1903 set_sock_opt.quickack_opt = true;
1904 if (element.socket_option_tcp_quickack == 1) {
1905 set_sock_opt.quickack_val = true;
1909 //----Debug log----------------------------------------------------------------------
1910 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1911 boost::format formatter("set_socket_option"
1912 " defer_accept_opt[%s]"
1913 " defer_accept_val[%d]"
1918 " keepalive_opt[%s]"
1919 " keepalive_val[%s]"
1921 " quickack_val[%s]");
1923 % (defer_accept_opt ? "true" : "false")
1925 % (set_sock_opt.nodelay_opt ? "true" : "false")
1926 % (set_sock_opt.nodelay_val ? "true" : "false")
1927 % (set_sock_opt.cork_opt ? "true" : "false")
1928 % (set_sock_opt.cork_val ? "true" : "false")
1929 % (set_sock_opt.keepalive_opt ? "true" : "false")
1930 % (set_sock_opt.keepalive_val ? "true" : "false")
1931 % (set_sock_opt.quickack_opt ? "true" : "false")
1932 % (set_sock_opt.quickack_val ? "true" : "false");
1933 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 97, formatter.str(), __FILE__, __LINE__);
1935 //----Debug log----------------------------------------------------------------------
1939 //! get private key file password (for callback function)
1940 //! @return password string
1941 std::string l7vs::virtualservice_tcp::get_ssl_password()
1943 //*-------- DEBUG LOG --------*/
1944 if (unlikely(LOG_LV_DEBUG ==
1945 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1946 std::stringstream buf;
1947 buf << "in_function: ";
1948 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password()";
1949 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 98, buf.str(),
1950 __FILE__, __LINE__);
1952 //*------ DEBUG LOG END ------*/
1954 // Get password from file.
1955 std::string retstr = "";
1957 char buf[MAX_SSL_PASSWD_SIZE + 3];
1958 if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1960 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1961 "Password file cannot open.", __FILE__, __LINE__);
1963 if (fgets(buf, MAX_SSL_PASSWD_SIZE + 3, fp) == NULL) {
1964 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
1965 "Password not found in file.",
1966 __FILE__, __LINE__);
1968 if (strlen(buf) > MAX_SSL_PASSWD_SIZE) {
1969 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1970 "Password is too long.",
1971 __FILE__, __LINE__);
1973 buf[strlen(buf) - 1] = '\0';
1980 //*-------- DEBUG LOG --------*/
1981 if (unlikely(LOG_LV_DEBUG ==
1982 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1983 std::stringstream buf;
1984 buf << "out_function: ";
1985 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password(): ";
1986 buf << "retstr = " << retstr;
1987 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 99, buf.str(),
1988 __FILE__, __LINE__);
1990 //*------ DEBUG LOG END ------*/
1996 //! Convert verify option string to integer(#define).
1998 //! @param[in] opt_string option string
1999 //! @retval ret option value
2000 //! @retval -1 no match
2001 int l7vs::virtualservice_tcp::conv_verify_option(std::string opt_string)
2003 //*-------- DEBUG LOG --------*/
2004 if (unlikely(LOG_LV_DEBUG ==
2005 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2006 std::stringstream buf;
2007 buf << "in_function: ";
2008 buf << "int virtualservice_tcp::conv_verify_option";
2009 buf << "(std::string opt_string): ";
2010 buf << "opt_string = " << opt_string;
2011 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 100, buf.str(),
2012 __FILE__, __LINE__);
2014 //*------ DEBUG LOG END ------*/
2018 // /usr/include/openssl/ssl.h
2019 // #define SSL_VERIFY_NONE 0x00
2020 // #define SSL_VERIFY_PEER 0x01
2021 // #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
2022 // #define SSL_VERIFY_CLIENT_ONCE 0x04
2024 if (opt_string == "SSL_VERIFY_NONE") {
2025 ret = SSL_VERIFY_NONE;
2026 } else if (opt_string == "SSL_VERIFY_PEER") {
2027 ret = SSL_VERIFY_PEER;
2028 } else if (opt_string == "SSL_VERIFY_FAIL_IF_NO_PEER_CERT") {
2029 ret = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2030 } else if (opt_string == "SSL_VERIFY_CLIENT_ONCE") {
2031 ret = SSL_VERIFY_CLIENT_ONCE;
2033 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2034 "verify option string no match.",
2035 __FILE__, __LINE__);
2038 //*-------- DEBUG LOG --------*/
2039 if (unlikely(LOG_LV_DEBUG ==
2040 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2041 std::stringstream buf;
2042 buf << "out_function: ";
2043 buf << "int virtualservice_tcp::conv_verify_option";
2044 buf << "(std::string opt_string): ";
2045 buf << "return_value = " << ret;
2046 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 101, buf.str(),
2047 __FILE__, __LINE__);
2049 //*------ DEBUG LOG END ------*/
2050 // if ret == -1 then No match.
2055 // Convert SSL option string to integer(#define).
2057 // @param[in] opt_string option string
2058 // @retval ret option value
2059 // @retval -1 no match
2060 long int l7vs::virtualservice_tcp::conv_ssl_option(std::string opt_string)
2062 //*-------- DEBUG LOG --------*/
2063 if (unlikely(LOG_LV_DEBUG ==
2064 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2065 std::stringstream buf;
2066 buf << "in_function: ";
2067 buf << "long int virtualservice_tcp::conv_ssl_option";
2068 buf << "(std::string opt_string): ";
2069 buf << "opt_string = " << opt_string;
2070 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 102, buf.str(),
2071 __FILE__, __LINE__);
2073 //*------ DEBUG LOG END ------*/
2077 // /usr/include/openssl/ssl.h
2078 // #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
2079 // #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
2080 // #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
2081 // #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
2082 // #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
2083 // #define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L
2084 // #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
2085 // #define SSL_OP_TLS_D5_BUG 0x00000100L
2086 // #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
2087 // #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L
2088 // #define SSL_OP_ALL 0x00000FF7L
2089 // #define SSL_OP_NO_QUERY_MTU 0x00001000L
2090 // #define SSL_OP_COOKIE_EXCHANGE 0x00002000L
2091 // #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
2092 // #define SSL_OP_SINGLE_ECDH_USE 0x00080000L
2093 // #define SSL_OP_SINGLE_DH_USE 0x00100000L
2094 // #define SSL_OP_EPHEMERAL_RSA 0x00200000L
2095 // #define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
2096 // #define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
2097 // #define SSL_OP_NO_SSLv2 0x01000000L
2098 // #define SSL_OP_NO_SSLv3 0x02000000L
2099 // #define SSL_OP_NO_TLSv1 0x04000000L
2100 // #define SSL_OP_PKCS1_CHECK_1 0x08000000L
2101 // #define SSL_OP_PKCS1_CHECK_2 0x10000000L
2102 // #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
2103 // #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
2104 if (opt_string == "SSL_OP_MICROSOFT_SESS_ID_BUG") {
2105 ret = SSL_OP_MICROSOFT_SESS_ID_BUG;
2106 } else if (opt_string == "SSL_OP_NETSCAPE_CHALLENGE_BUG") {
2107 ret = SSL_OP_NETSCAPE_CHALLENGE_BUG;
2108 } else if (opt_string == "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG") {
2109 ret = SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
2110 } else if (opt_string == "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG") {
2111 ret = SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
2112 } else if (opt_string == "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER") {
2113 ret = SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
2114 } else if (opt_string == "SSL_OP_MSIE_SSLV2_RSA_PADDING") {
2115 ret = SSL_OP_MSIE_SSLV2_RSA_PADDING;
2116 } else if (opt_string == "SSL_OP_SSLEAY_080_CLIENT_DH_BUG") {
2117 ret = SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
2118 } else if (opt_string == "SSL_OP_TLS_D5_BUG") {
2119 ret = SSL_OP_TLS_D5_BUG;
2120 } else if (opt_string == "SSL_OP_TLS_BLOCK_PADDING_BUG") {
2121 ret = SSL_OP_TLS_BLOCK_PADDING_BUG;
2122 } else if (opt_string == "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS") {
2123 ret = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
2124 } else if (opt_string == "SSL_OP_ALL") {
2125 // boost::asio::ssl::context::default_workarounds
2127 } else if (opt_string == "SSL_OP_NO_QUERY_MTU") {
2128 ret = SSL_OP_NO_QUERY_MTU;
2129 } else if (opt_string == "SSL_OP_COOKIE_EXCHANGE") {
2130 ret = SSL_OP_COOKIE_EXCHANGE;
2131 } else if (opt_string == "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION") {
2132 ret = SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
2133 } else if (opt_string == "SSL_OP_SINGLE_ECDH_USE") {
2134 ret = SSL_OP_SINGLE_ECDH_USE;
2135 } else if (opt_string == "SSL_OP_SINGLE_DH_USE") {
2136 // boost::asio::ssl::context::single_dh_use
2137 ret = SSL_OP_SINGLE_DH_USE;
2138 } else if (opt_string == "SSL_OP_EPHEMERAL_RSA") {
2139 ret = SSL_OP_EPHEMERAL_RSA;
2140 } else if (opt_string == "SSL_OP_CIPHER_SERVER_PREFERENCE") {
2141 ret = SSL_OP_CIPHER_SERVER_PREFERENCE;
2142 } else if (opt_string == "SSL_OP_TLS_ROLLBACK_BUG") {
2143 ret = SSL_OP_TLS_ROLLBACK_BUG;
2144 } else if (opt_string == "SSL_OP_NO_SSLv2") {
2145 // boost::asio::ssl::context::no_sslv2
2146 ret = SSL_OP_NO_SSLv2;
2147 } else if (opt_string == "SSL_OP_NO_SSLv3") {
2148 // boost::asio::ssl::context::no_sslv3
2149 ret = SSL_OP_NO_SSLv3;
2150 } else if (opt_string == "SSL_OP_NO_TLSv1") {
2151 // boost::asio::ssl::context::no_tlsv1
2152 ret = SSL_OP_NO_TLSv1;
2153 } else if (opt_string == "SSL_OP_PKCS1_CHECK_1") {
2154 ret = SSL_OP_PKCS1_CHECK_1;
2155 } else if (opt_string == "SSL_OP_PKCS1_CHECK_2") {
2156 ret = SSL_OP_PKCS1_CHECK_2;
2157 } else if (opt_string == "SSL_OP_NETSCAPE_CA_DN_BUG") {
2158 ret = SSL_OP_NETSCAPE_CA_DN_BUG;
2159 } else if (opt_string == "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG") {
2160 ret = SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
2162 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
2163 "ssl option string no match.",
2164 __FILE__, __LINE__);
2167 //*-------- DEBUG LOG --------*/
2168 if (unlikely(LOG_LV_DEBUG ==
2169 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2170 std::stringstream buf;
2171 buf << "out_function: ";
2172 buf << "long int virtualservice_tcp::conv_ssl_option";
2173 buf << "(std::string opt_string): ";
2174 buf << "return_value = " << ret;
2175 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 103, buf.str(),
2176 __FILE__, __LINE__);
2178 //------ DEBUG LOG END ------*/
2179 // if ret == -1 then No match.
2184 //! get ssl parameter
2185 //! @return get ssl parameter result
2186 bool l7vs::virtualservice_tcp::get_ssl_parameter()
2188 //*-------- DEBUG LOG --------*/
2189 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2190 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 104,
2191 "in_function: bool virtualservice_tcp::get_ssl_parameter()",
2192 __FILE__, __LINE__);
2194 //*------ DEBUG LOG END ------*/
2195 typedef std::vector< std::string > string_vector_type;
2198 string_vector_type string_vector;
2199 l7vs::error_code err;
2200 bool retbool = false;
2203 // param init ( ssl configuration file )
2204 if (unlikely(!param.init(l7vs::PARAM_COMP_SSL, ssl_file_name))) {
2205 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 24,
2206 "SSL config file read error.",
2207 __FILE__, __LINE__);
2211 //// SSL context parameter
2212 // Get parameter "ca_dir".
2213 ca_dir = param.get_string(l7vs::PARAM_COMP_SSL, "ca_dir",
2214 err, ssl_file_name);
2215 if (unlikely(err) || ca_dir == "") {
2216 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 9,
2217 "ca_dir parameter not found. Use default value.",
2218 __FILE__, __LINE__);
2219 ca_dir = DEFAULT_SSL_CA_DIR;
2222 // Get parameter "ca_file".
2223 ca_file = param.get_string(l7vs::PARAM_COMP_SSL, "ca_file",
2224 err, ssl_file_name);
2225 if (unlikely(err)) {
2226 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 25,
2227 "Cannot get ca_file parameter.",
2228 __FILE__, __LINE__);
2232 // Get parameter "cert_chain_dir".
2233 cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2237 if (unlikely(err) || cert_chain_dir == "") {
2238 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 10,
2239 "cert_chain_dir parameter not found. Use default value.",
2240 __FILE__, __LINE__);
2241 cert_chain_dir = DEFAULT_SSL_CERT_CHAIN_DIR;
2244 // Get parameter "cert_chain_file".
2245 cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
2249 if (unlikely(err) || cert_chain_file == "") {
2250 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 26,
2251 "Cannot get cert_chain_file parameter.",
2252 __FILE__, __LINE__);
2256 // Get parameter "private_key_dir".
2257 private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2261 if (unlikely(err) || private_key_dir == "") {
2262 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 11,
2263 "private_key_dir parameter not found. Use default value.",
2264 __FILE__, __LINE__);
2265 private_key_dir = DEFAULT_SSL_PRIVATE_KEY_DIR;
2268 // Get parameter "private_key_file".
2269 private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
2273 if (unlikely(err) || private_key_file == "") {
2274 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 27,
2275 "Cannot get private_key_file parameter.",
2276 __FILE__, __LINE__);
2280 // Get parameter "private_key_filetype".
2281 // and convert string to filetype define value.
2283 // /usr/include/openssl/ssl.h
2284 // #define SSL_FILETYPE_PEM X509_FILETYPE_PEM ->1
2285 // #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 ->2
2286 std::string filetype_str = param.get_string(
2287 l7vs::PARAM_COMP_SSL,
2288 "private_key_filetype",
2291 if (unlikely(err) || filetype_str == "") {
2292 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 12,
2293 "private_key_filetype parameter not found. Use default value.",
2294 __FILE__, __LINE__);
2295 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
2296 } else if (filetype_str == "SSL_FILETYPE_PEM") {
2297 private_key_filetype = boost::asio::ssl::context::pem;
2298 } else if (filetype_str == "SSL_FILETYPE_ASN1") {
2299 private_key_filetype = boost::asio::ssl::context::asn1;
2301 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
2302 "private_key_filetype convert error.",
2303 __FILE__, __LINE__);
2307 // Get parameter "private_key_passwd_dir".
2308 private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2309 "private_key_passwd_dir",
2312 if (unlikely(err) || private_key_passwd_dir == "") {
2313 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 13,
2314 "private_key_passwd_dir parameter not found. Use default value.",
2315 __FILE__, __LINE__);
2316 private_key_passwd_dir = DEFAULT_SSL_PRIVATE_KEY_PASSWD_DIR;
2319 // Get parameter "private_key_passwd_file".
2320 private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2321 "private_key_passwd_file",
2324 if (unlikely(err) || private_key_passwd_file == "") {
2325 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
2326 "Cannot get private_key_passwd_file parameter.",
2327 __FILE__, __LINE__);
2331 // Get parameter "verify_options".
2332 param.get_multistring(l7vs::PARAM_COMP_SSL,
2337 if (unlikely(err)) {
2338 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 14,
2339 "verify_options parameter not found. Use default value.",
2340 __FILE__, __LINE__);
2341 verify_options = DEFAULT_SSL_VERIFY_OPTIONS;
2343 // Make verify option bit data.
2344 for (string_vector_type::iterator itr = string_vector.begin();
2345 itr != string_vector.end(); ++itr) {
2346 // Convert string to define value.
2347 int int_val = conv_verify_option(*itr);
2348 if (unlikely(int_val == -1)) {
2349 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 30,
2350 "verify_options convert error.",
2351 __FILE__, __LINE__);
2354 verify_options = (verify_options | int_val);
2358 // Get parameter "verify_cert_depth".
2359 verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2360 "verify_cert_depth",
2363 if (unlikely(err)) {
2364 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 15,
2365 "verify_cert_depth parameter not found. Use default value.",
2366 __FILE__, __LINE__);
2367 verify_cert_depth = DEFAULT_SSL_VERIFY_CERT_DEPTH;
2368 } else if (unlikely(verify_cert_depth < 0 ||
2369 verify_cert_depth > INT_MAX)) {
2370 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 31,
2371 "Invalid verify_cert_depth parameter value.",
2372 __FILE__, __LINE__);
2376 // Get parameter "ssl_options".
2377 // and Check dh parameter file use or not.
2378 is_tmp_dh_use = false;
2379 param.get_multistring(l7vs::PARAM_COMP_SSL,
2384 if (unlikely(err)) {
2385 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 16,
2386 "ssl_options parameter not found. Use default value.",
2387 __FILE__, __LINE__);
2388 ssl_options = DEFAULT_SSL_OPTIONS;
2389 is_tmp_dh_use = true;
2391 // Make ssl option bit data.
2392 for (string_vector_type::iterator itr = string_vector.begin();
2393 itr != string_vector.end(); ++itr) {
2394 // Convert string to define value.
2395 long int longint_val = conv_ssl_option(*itr);
2396 if (unlikely(longint_val == -1)) {
2397 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 32,
2398 "ssl_options convert error.",
2399 __FILE__, __LINE__);
2401 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2402 is_tmp_dh_use = true;
2404 ssl_options = (ssl_options | longint_val);
2408 if (is_tmp_dh_use) {
2409 // Get parameter "tmp_dh_dir".
2410 tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2414 if (unlikely(err) || tmp_dh_dir == "") {
2415 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
2416 "tmp_dh_dir parameter not found. Use default value.",
2417 __FILE__, __LINE__);
2418 tmp_dh_dir = DEFAULT_SSL_TMP_DH_DIR;
2420 // Get parameter "tmp_dh_file".
2421 tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2425 if (unlikely(err) || tmp_dh_file == "") {
2426 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 33,
2427 "Cannot get tmp_dh_file parameter.",
2428 __FILE__, __LINE__);
2433 // Get parameter "cipher_list".
2434 cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2438 if (unlikely(err) || cipher_list == "") {
2439 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 18,
2440 "cipher_list parameter not found. Use default value.",
2441 __FILE__, __LINE__);
2442 cipher_list = DEFAULT_SSL_CIPHER_LIST;
2445 //// SSL session cache parameter
2446 // Get parameter "session_cache".
2447 is_session_cache_use = false;
2448 std::string cache_str = param.get_string(l7vs::PARAM_COMP_SSL,
2452 if (unlikely(err) || cache_str == "") {
2453 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
2454 "session_cache parameter not found. Use default value.",
2455 __FILE__, __LINE__);
2456 is_session_cache_use = true;
2457 } else if (cache_str == "on") {
2458 is_session_cache_use = true;
2459 } else if (cache_str == "off") {
2460 is_session_cache_use = false;
2462 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2463 "Invalid session_cache parameter value.", __FILE__, __LINE__);
2467 if (is_session_cache_use) {
2468 session_cache_mode = DEFAULT_SSL_SESSION_CACHE_MODE;
2469 // Get parameter "session_cache_size".
2470 session_cache_size = param.get_int(l7vs::PARAM_COMP_SSL,
2471 "session_cache_size",
2474 if (unlikely(err)) {
2475 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
2476 "session_cache_size parameter not found. Use default value.",
2477 __FILE__, __LINE__);
2478 session_cache_size = DEFAULT_SSL_SESSION_CACHE_SIZE;
2479 } else if (session_cache_size < 0 ||
2480 session_cache_size > INT_MAX) {
2481 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 35,
2482 "Invalid session_cache_size parameter value.", __FILE__, __LINE__);
2485 // Get parameter "session_cache_timeout".
2486 session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2487 "session_cache_timeout",
2490 if (unlikely(err)) {
2491 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
2492 "session_cache_timeout parameter not found. Use default value.",
2493 __FILE__, __LINE__);
2494 session_cache_timeout = DEFAULT_SSL_SESSION_CACHE_TIMEOUT;
2495 } else if (session_cache_timeout < 0 ||
2496 session_cache_timeout > INT_MAX) {
2497 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 36,
2498 "Invalid session_cache_timeout parameter value.",
2499 __FILE__, __LINE__);
2503 session_cache_mode = SSL_SESS_CACHE_OFF;
2506 //// SSL handshake timer parameter
2507 // Get parameter "timeout_sec".
2508 handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2512 if (unlikely(err)) {
2513 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2514 "timeout_sec parameter not found. Use default value.", __FILE__, __LINE__);
2515 handshake_timeout = DEFAULT_SSL_HANDSHAKE_TIMEOUT;
2516 } else if (handshake_timeout <= 0 || handshake_timeout > INT_MAX) {
2517 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 37,
2518 "Invalid timeout_sec parameter value.", __FILE__, __LINE__);
2528 //*-------- DEBUG LOG --------*/
2529 if (unlikely(LOG_LV_DEBUG ==
2530 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2531 std::stringstream buf;
2532 buf << "out_function: bool virtualservice_tcp::get_ssl_parameter(): ";
2533 buf << "ca_dir = " << ca_dir << ", ";
2534 buf << "ca_file = " << ca_file << ", ";
2535 buf << "cert_chain_dir = " << cert_chain_dir << ", ";
2536 buf << "cert_chain_file = " << cert_chain_file << ", ";
2537 buf << "private_key_dir = " << private_key_dir << ", ";
2538 buf << "private_key_file = " << private_key_file << ", ";
2539 buf << "private_key_filetype = " << private_key_filetype << ", ";
2540 buf << "private_key_passwd_dir = " << private_key_passwd_dir << ", ";
2541 buf << "private_key_passwd_file = " << private_key_passwd_file << ", ";
2542 buf << "verify_options = " << verify_options << ", ";
2543 buf << "verify_cert_depth = " << verify_cert_depth << ", ";
2544 buf << "ssl_options = " << ssl_options << ", ";
2545 if (is_tmp_dh_use) {
2546 buf << "tmp_dh_dir = " << tmp_dh_dir << ", ";
2547 buf << "tmp_dh_file = " << tmp_dh_file << ", ";
2549 buf << "cipher_list = " << cipher_list << ", ";
2550 buf << "session_cache_mode = " << session_cache_mode << ", ";
2551 if (is_session_cache_use) {
2552 buf << "session_cache_size = " << session_cache_size << ", ";
2553 buf << "session_cache_timeout = " << session_cache_timeout << ", ";
2555 buf << "handshake_timeout = " << handshake_timeout;
2556 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2558 __FILE__, __LINE__);
2560 //*------ DEBUG LOG END ------*/
2565 // set ssl context and ssl session cache configuration
2566 // @return set ssl config result
2567 bool l7vs::virtualservice_tcp::set_ssl_config()
2569 //*-------- DEBUG LOG --------*/
2570 if (unlikely(LOG_LV_DEBUG ==
2571 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2572 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 106,
2573 "in_function: bool virtualservice_tcp::set_ssl_config()",
2574 __FILE__, __LINE__);
2576 //*------ DEBUG LOG END ------*/
2578 bool retbool = false;
2581 //// SSL context setting.
2583 if (ca_file.size() == 0) {
2584 // specified CA path.
2586 sslcontext->add_verify_path(ca_dir);
2587 } catch (std::exception &e) {
2588 std::stringstream buf;
2589 buf << "Set root CA path error: " << e.what() << ".";
2590 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2592 __FILE__, __LINE__);
2596 // specified CA file.
2598 sslcontext->load_verify_file(ca_dir + ca_file);
2599 } catch (std::exception &e) {
2600 std::stringstream buf;
2601 buf << "Set root CA file error: " << e.what() << ".";
2602 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2604 __FILE__, __LINE__);
2609 // Set certificate chain file.
2611 sslcontext->use_certificate_chain_file(
2612 cert_chain_dir + cert_chain_file);
2613 } catch (std::exception &e) {
2614 std::stringstream buf;
2615 buf << "Set certificate chain file error: " << e.what() << ".";
2616 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2617 __FILE__, __LINE__);
2621 // Set password callback function.
2623 sslcontext->set_password_callback(
2624 boost::bind(&virtualservice_tcp::get_ssl_password, this));
2625 } catch (std::exception &e) {
2626 std::stringstream buf;
2627 buf << "Set password callback error: " << e.what() << ".";
2628 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2629 __FILE__, __LINE__);
2633 // Set private key file and filetype.
2635 sslcontext->use_private_key_file(
2636 private_key_dir + private_key_file, private_key_filetype);
2637 } catch (std::exception &e) {
2638 std::stringstream buf;
2639 buf << "Set private key file and filetype error: " << e.what() << ".";
2640 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2641 __FILE__, __LINE__);
2645 // Set verify options on the context.
2647 sslcontext->set_verify_mode(verify_options);
2648 } catch (std::exception &e) {
2649 std::stringstream buf;
2650 buf << "Set verify option error: " << e.what() << ".";
2651 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2652 __FILE__, __LINE__);
2656 // Set verify depth on the context.
2657 SSL_CTX_set_verify_depth(sslcontext->impl(), verify_cert_depth);
2659 // Set SSL options on the context.
2661 sslcontext->set_options(ssl_options);
2662 } catch (std::exception &e) {
2663 std::stringstream buf;
2664 buf << "Set SSL option error: " << e.what() << ".";
2665 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2666 __FILE__, __LINE__);
2670 // Set temporary Diffie-Hellman parameters file.
2671 if (is_tmp_dh_use) {
2673 sslcontext->use_tmp_dh_file(tmp_dh_dir + tmp_dh_file);
2674 } catch (std::exception &e) {
2675 std::stringstream buf;
2676 buf << "Set tmp DH file error: " << e.what() << ".";
2677 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2679 __FILE__, __LINE__);
2685 // Set cipher list on the context.
2686 if (unlikely(SSL_CTX_set_cipher_list(sslcontext->impl(),
2687 cipher_list.c_str()) != 1)) {
2688 std::stringstream buf;
2689 buf << "Set cipher list error.";
2690 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2692 __FILE__, __LINE__);
2696 //// SSL session cache setting.
2697 if (is_session_cache_use) {
2698 // Set session id context on the context.
2699 if (unlikely(SSL_CTX_set_session_id_context(
2701 (const unsigned char *)"ultramonkey", 11) != 1)) {
2702 std::stringstream buf;
2703 buf << "Set session id context error.";
2704 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2706 __FILE__, __LINE__);
2710 // Set session cache mode on the context.
2711 SSL_CTX_set_session_cache_mode(
2712 sslcontext->impl(), session_cache_mode);
2714 // Set session cache size on the context.
2715 SSL_CTX_sess_set_cache_size(sslcontext->impl(), session_cache_size);
2717 // Set session cache timeout on the context.
2718 SSL_CTX_set_timeout(sslcontext->impl(), session_cache_timeout);
2721 // session cache OFF.
2722 SSL_CTX_set_session_cache_mode(sslcontext->impl(),
2723 SSL_SESS_CACHE_OFF);
2731 //*-------- DEBUG LOG --------*/
2732 if (unlikely(LOG_LV_DEBUG ==
2733 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2734 std::stringstream buf;
2735 buf << "out_function: bool virtualservice_tcp::set_ssl_config(): ";
2736 get_ssl_config(buf);
2737 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 117, buf.str(),
2738 __FILE__, __LINE__);
2740 //*------ DEBUG LOG END ------*/
2745 // flush ssl session
2746 void l7vs::virtualservice_tcp::flush_ssl_session()
2748 // check expired cached sessions and do flushing
2749 // Need ssl_context lock?
2750 SSL_CTX_flush_sessions(sslcontext->impl(), time(0));
2754 // get ssl configuration form ssl context. (for debug)
2755 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream &buf)
2757 buf << "SSL configuration information: ";
2758 buf << "Verify mode[" << SSL_CTX_get_verify_mode(sslcontext->impl()) << "] ";
2759 buf << "Verify depth[" << SSL_CTX_get_verify_depth(sslcontext->impl()) << "] ";
2760 buf << "SSL options[" << SSL_CTX_get_options(sslcontext->impl()) << "] ";
2761 buf << "Cache mode[" << SSL_CTX_get_session_cache_mode(sslcontext->impl()) << "] ";
2762 buf << "Cache size[" << SSL_CTX_sess_get_cache_size(sslcontext->impl()) << "] ";
2763 buf << "Cache timeout[" << SSL_CTX_get_timeout(sslcontext->impl()) << "] ";
2767 // get ssl session cache information form ssl context. (for debug)
2768 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream &buf)
2770 buf << "SSL session cache information: ";
2771 buf << "Session number[" << SSL_CTX_sess_number(sslcontext->impl()) << "] ";
2772 buf << "Accept[" << SSL_CTX_sess_accept(sslcontext->impl()) << "] ";
2773 buf << "Accept good[" << SSL_CTX_sess_accept_good(sslcontext->impl()) << "] ";
2774 buf << "Accept renegotiate[" << SSL_CTX_sess_accept_renegotiate(sslcontext->impl()) << "] ";
2775 buf << "Hits[" << SSL_CTX_sess_hits(sslcontext->impl()) << "] ";
2776 buf << "Misses[" << SSL_CTX_sess_misses(sslcontext->impl()) << "] ";
2777 buf << "Timeouts[" << SSL_CTX_sess_timeouts(sslcontext->impl()) << "] ";
2778 buf << "Cache full[" << SSL_CTX_sess_cache_full(sslcontext->impl()) << "] ";