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 rs_list.erase(rs_itr);
1532 active_sessions.do_all(boost::bind(&session_thread_control::session_realserver_remove, _1, rs_itr->tcp_endpoint));
1538 //lock adm_cmd_wait_flag off
1539 adm_cmd_wait_flag_mutex.lock();
1540 adm_cmd_wait_flag = false;
1541 adm_cmd_wait_flag_cond.notify_one();
1542 adm_cmd_wait_flag_mutex.unlock();
1544 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1545 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1546 "const l7vs::virtualservice_element& in,"
1547 "l7vs::error_code& err ): err = %s, err.message = %s");
1548 formatter % (err ? "true" : "false") % err.get_message();
1549 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 79, formatter.str(), __FILE__, __LINE__);
1554 * main loop of virtualservice(TCP)
1559 void l7vs::virtualservice_tcp::run()
1561 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function: void virtualservice_tcp::run()",
1562 __FILE__, __LINE__);
1564 if (pool_sessions.size() == 0) {
1565 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.",
1566 __FILE__, __LINE__);
1569 boost::asio::socket_base::receive_buffer_size option(8192 * 192);
1570 acceptor_->set_option(option);
1571 //set socket option TCP_DEFER_ACCEPT
1572 if (defer_accept_opt) {
1573 size_t len = sizeof(defer_accept_val);
1574 int err = ::setsockopt(acceptor_->native(), IPPROTO_TCP, TCP_DEFER_ACCEPT, &defer_accept_val, len);
1575 if (unlikely(err)) {
1577 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
1578 "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__);
1582 acceptor_->listen();
1584 //left session is less than the threshold
1585 if ((sessionpool_alert_flag == false) &&
1586 (pool_sessions.size() < param_data.session_pool_alert_on)) {
1587 //create trap message
1588 trapmessage trap_msg;
1589 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
1590 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
1591 error_code err_code;
1592 //push the trap message
1593 snmpagent::push_trapmessage(trap_msg, err_code);
1595 std::string msg("Push trap message failed.");
1596 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, msg, __FILE__, __LINE__);
1599 //set sessionpool alert flag true
1600 sessionpool_alert_flag = true;
1603 //switch active a session
1604 session_thread_control *stc_ptr;
1606 stc_ptr = pool_sessions.pop();
1609 waiting_session = stc_ptr->get_session().get();
1610 waiting_stc = stc_ptr;
1612 if (!ssl_virtualservice_mode_flag) {
1613 acceptor_->async_accept(waiting_session->get_client_socket().get_socket(),
1614 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1615 boost::asio::placeholders::error));
1617 acceptor_->async_accept(waiting_session->get_client_ssl_socket().lowest_layer(),
1618 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1619 boost::asio::placeholders::error));
1621 //register timer event handler
1622 calc_bps_timer->expires_from_now(boost::posix_time::milliseconds(param_data.bps_interval));
1623 calc_bps_timer->async_wait(boost::bind(&virtualservice_tcp::handle_throughput_update,
1624 this, boost::asio::placeholders::error));
1626 //register handle_replication_interrupt
1627 replication_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1628 replication_timer->async_wait(boost::bind(&virtualservice_tcp::handle_replication_interrupt,
1629 this, boost::asio::placeholders::error));
1630 //register handle_protomod_replication
1631 protomod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1632 protomod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_protomod_replication,
1633 this, boost::asio::placeholders::error));
1634 //register handle_schedmod_replication
1635 schedmod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1636 schedmod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_schedmod_replication,
1637 this, boost::asio::placeholders::error));
1639 //run dispatcher(start io_service loop)
1640 work.reset(new boost::asio::io_service::work(*dispatcher));
1641 boost::thread_group dispatcher_thread_group;
1643 for (int i = 0; i < IO_SERVICE_THREADS_NUM; i++) {
1644 dispatcher_thread_group.create_thread(boost::bind(&boost::asio::io_service::run, dispatcher));
1647 //join dispatcher_thread_group when virtualservice_tcp::stop() executed.
1648 dispatcher_thread_group.join_all();
1657 void l7vs::virtualservice_tcp::stop()
1659 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function: void virtualservice_tcp::stop()",
1660 __FILE__, __LINE__);
1662 boost::system::error_code err;
1663 virtualservice_stop_flag++;
1664 while (interrupt_running_flag.get()) {
1665 boost::this_thread::yield();
1668 acceptor_->close(err);
1670 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__);
1675 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1676 active_sessions.do_all(boost::bind(&session_thread_control::session_stop, _1));
1677 while (active_sessions.size()) {
1678 boost::this_thread::yield();
1682 calc_bps_timer->cancel();
1683 replication_timer->cancel();
1684 protomod_rep_timer->cancel();
1685 schedmod_rep_timer->cancel();
1688 dispatcher->reset();
1694 * increment active-connection count
1699 void l7vs::virtualservice_tcp::connection_active(const boost::asio::ip::tcp::endpoint &in)
1701 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1702 boost::format formatter("in_function: void virtualservice_tcp::connection_active( "
1703 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1705 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__);
1708 for (std::list<realserver>::iterator itr = rs_list.begin();
1709 itr != rs_list.end();
1711 if (itr->tcp_endpoint == in) {
1712 itr->increment_active();
1719 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1720 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 83, "out_function: "
1721 "void virtualservice_tcp::connection_active()", __FILE__, __LINE__);
1726 * increment in-active-connection (and decrement active-connection count)
1731 void l7vs::virtualservice_tcp::connection_inactive(const boost::asio::ip::tcp::endpoint &in)
1733 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1734 boost::format formatter("in_function: void virtualservice_tcp::connection_inactive( "
1735 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1737 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__);
1740 for (std::list<realserver>::iterator itr = rs_list.begin();
1741 itr != rs_list.end();
1743 if (itr->tcp_endpoint == in) {
1744 itr->decrement_active();
1745 itr->increment_inact();
1752 //left session is more than the release threshold
1753 if ((sessionpool_alert_flag == true) &&
1754 ((pool_sessions.size() + 1) > param_data.session_pool_alert_off)) {
1755 //create trap message
1756 trapmessage trap_msg;
1757 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_OFF;
1758 trap_msg.message = "TRAP00020012,Warning release: The left-session has exceeded the release threshold of left-session warning.";
1759 error_code err_code;
1760 //push the trap message
1761 snmpagent::push_trapmessage(trap_msg, err_code);
1763 std::string msg("Push trap message failed.");
1764 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 39, msg, __FILE__, __LINE__);
1767 //set sessionpool alert flag true
1768 sessionpool_alert_flag = false;
1771 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1772 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 85, "out_function: "
1773 "void virtualservice_tcp::connection_inactive()", __FILE__, __LINE__);
1783 void l7vs::virtualservice_tcp::release_session(const tcp_session *session_ptr)
1785 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1786 boost::format funclog_fmt("in_function: void virtualservice_tcp::release_session( "
1787 "const tcp_session* session_ptr ): session_ptr = %d");
1788 funclog_fmt % session_ptr;
1789 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 86, funclog_fmt.str(), __FILE__, __LINE__);
1792 session_thread_control *stc_ptr = active_sessions.find(session_ptr);
1793 if (unlikely(NULL == stc_ptr)) {
1794 boost::format fmt("session release fail: "
1795 "active_sessions.find( const tcp_session* session_ptr = %d )");
1797 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*XXX*/999, fmt.str(), __FILE__, __LINE__);
1798 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1799 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 88, "out_function: "
1800 "void virtualservice_tcp::release_session( "
1801 "const boost::thread::id thread_id )", __FILE__, __LINE__);
1806 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1807 boost::format fmt1("pool_session.size = %d");
1808 fmt1 % pool_sessions.size();
1809 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 89, fmt1.str(), __FILE__, __LINE__);
1810 boost::format fmt2("active_session.size = %d");
1811 fmt2 % active_sessions.size();
1812 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 90, fmt2.str(), __FILE__, __LINE__);
1813 boost::format fmt3("active_count = %d");
1814 fmt3 % active_count.get();
1815 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 91, fmt3.str(), __FILE__, __LINE__);
1817 active_sessions.erase(session_ptr);
1819 while (!pool_sessions.push(stc_ptr)) {}
1821 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1822 boost::format fmt1("pool_session.size = %d");
1823 fmt1 % pool_sessions.size();
1824 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 92, fmt1.str(), __FILE__, __LINE__);
1825 boost::format fmt2("active_session.size = %d");
1826 fmt2 % active_sessions.size();
1827 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 93, fmt2.str(), __FILE__, __LINE__);
1828 boost::format fmt3("active_count = %d");
1829 fmt3 % active_count.get();
1830 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 94, fmt3.str(), __FILE__, __LINE__);
1832 boost::format funclog_fmt("out_function: void virtualservice_tcp::release_session( "
1833 "const tcp_session* session_ptr ): session_ptr = %d");
1834 funclog_fmt % session_ptr;
1835 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 95, funclog_fmt.str(), __FILE__, __LINE__);
1840 // set_socket_option
1842 void l7vs::virtualservice_tcp::set_socket_option()
1845 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1846 boost::format funclog_fmt("in_function: void virtualservice_tcp::et_socket_option");
1847 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 96, funclog_fmt.str(), __FILE__, __LINE__);
1850 // socket option check & set
1851 //! TCP_DEFER_ACCEPT (false:not set,true:set option)
1852 defer_accept_opt = false;
1853 //! TCP_DEFER_ACCEPT option value
1854 defer_accept_val = 0;
1855 //! TCP_NODELAY (false:not set,true:set option)
1856 set_sock_opt.nodelay_opt = false;
1857 //! TCP_NODELAY option value (false:off,true:on)
1858 set_sock_opt.nodelay_val = false;
1859 //! TCP_CORK (false:not set,true:set option)
1860 set_sock_opt.cork_opt = false;
1861 //! TCP_CORK option value (false:off,true:on)
1862 set_sock_opt.cork_val = false;
1863 //! TCP_QUICKACK (false:not set,true:set option)
1864 set_sock_opt.quickack_opt = false;
1865 //! TCP_QUICKACK option value (false:off,true:on)
1866 set_sock_opt.quickack_val = false;
1868 // set socket option
1869 if (element.socket_option_tcp_defer_accept != 0) {
1870 defer_accept_opt = true;
1871 if (element.socket_option_tcp_defer_accept == 1) {
1872 defer_accept_val = 1;
1876 if (element.socket_option_tcp_nodelay != 0) {
1877 set_sock_opt.nodelay_opt = true;
1878 if (element.socket_option_tcp_nodelay == 1) {
1879 set_sock_opt.nodelay_val = true;
1883 if (element.socket_option_tcp_cork != 0) {
1884 set_sock_opt.cork_opt = true;
1885 if (element.socket_option_tcp_cork == 1) {
1886 set_sock_opt.cork_val = true;
1890 if (element.socket_option_tcp_quickack != 0) {
1891 set_sock_opt.quickack_opt = true;
1892 if (element.socket_option_tcp_quickack == 1) {
1893 set_sock_opt.quickack_val = true;
1897 //----Debug log----------------------------------------------------------------------
1898 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1899 boost::format formatter("set_socket_option"
1900 " defer_accept_opt[%s]"
1901 " defer_accept_val[%d]"
1907 " quickack_val[%s]");
1909 % (defer_accept_opt ? "true" : "false")
1911 % (set_sock_opt.nodelay_opt ? "true" : "false")
1912 % (set_sock_opt.nodelay_val ? "true" : "false")
1913 % (set_sock_opt.cork_opt ? "true" : "false")
1914 % (set_sock_opt.cork_val ? "true" : "false")
1915 % (set_sock_opt.quickack_opt ? "true" : "false")
1916 % (set_sock_opt.quickack_val ? "true" : "false");
1917 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 97, formatter.str(), __FILE__, __LINE__);
1919 //----Debug log----------------------------------------------------------------------
1923 //! get private key file password (for callback function)
1924 //! @return password string
1925 std::string l7vs::virtualservice_tcp::get_ssl_password()
1927 //*-------- DEBUG LOG --------*/
1928 if (unlikely(LOG_LV_DEBUG ==
1929 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1930 std::stringstream buf;
1931 buf << "in_function: ";
1932 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password()";
1933 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 98, buf.str(),
1934 __FILE__, __LINE__);
1936 //*------ DEBUG LOG END ------*/
1938 // Get password from file.
1939 std::string retstr = "";
1941 char buf[MAX_SSL_PASSWD_SIZE + 3];
1942 if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1944 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1945 "Password file cannot open.", __FILE__, __LINE__);
1947 if (fgets(buf, MAX_SSL_PASSWD_SIZE + 3, fp) == NULL) {
1948 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
1949 "Password not found in file.",
1950 __FILE__, __LINE__);
1952 if (strlen(buf) > MAX_SSL_PASSWD_SIZE) {
1953 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1954 "Password is too long.",
1955 __FILE__, __LINE__);
1957 buf[strlen(buf) - 1] = '\0';
1964 //*-------- DEBUG LOG --------*/
1965 if (unlikely(LOG_LV_DEBUG ==
1966 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1967 std::stringstream buf;
1968 buf << "out_function: ";
1969 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password(): ";
1970 buf << "retstr = " << retstr;
1971 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 99, buf.str(),
1972 __FILE__, __LINE__);
1974 //*------ DEBUG LOG END ------*/
1980 //! Convert verify option string to integer(#define).
1982 //! @param[in] opt_string option string
1983 //! @retval ret option value
1984 //! @retval -1 no match
1985 int l7vs::virtualservice_tcp::conv_verify_option(std::string opt_string)
1987 //*-------- DEBUG LOG --------*/
1988 if (unlikely(LOG_LV_DEBUG ==
1989 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1990 std::stringstream buf;
1991 buf << "in_function: ";
1992 buf << "int virtualservice_tcp::conv_verify_option";
1993 buf << "(std::string opt_string): ";
1994 buf << "opt_string = " << opt_string;
1995 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 100, buf.str(),
1996 __FILE__, __LINE__);
1998 //*------ DEBUG LOG END ------*/
2002 // /usr/include/openssl/ssl.h
2003 // #define SSL_VERIFY_NONE 0x00
2004 // #define SSL_VERIFY_PEER 0x01
2005 // #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
2006 // #define SSL_VERIFY_CLIENT_ONCE 0x04
2008 if (opt_string == "SSL_VERIFY_NONE") {
2009 ret = SSL_VERIFY_NONE;
2010 } else if (opt_string == "SSL_VERIFY_PEER") {
2011 ret = SSL_VERIFY_PEER;
2012 } else if (opt_string == "SSL_VERIFY_FAIL_IF_NO_PEER_CERT") {
2013 ret = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2014 } else if (opt_string == "SSL_VERIFY_CLIENT_ONCE") {
2015 ret = SSL_VERIFY_CLIENT_ONCE;
2017 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2018 "verify option string no match.",
2019 __FILE__, __LINE__);
2022 //*-------- DEBUG LOG --------*/
2023 if (unlikely(LOG_LV_DEBUG ==
2024 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2025 std::stringstream buf;
2026 buf << "out_function: ";
2027 buf << "int virtualservice_tcp::conv_verify_option";
2028 buf << "(std::string opt_string): ";
2029 buf << "return_value = " << ret;
2030 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 101, buf.str(),
2031 __FILE__, __LINE__);
2033 //*------ DEBUG LOG END ------*/
2034 // if ret == -1 then No match.
2039 // Convert SSL option string to integer(#define).
2041 // @param[in] opt_string option string
2042 // @retval ret option value
2043 // @retval -1 no match
2044 long int l7vs::virtualservice_tcp::conv_ssl_option(std::string opt_string)
2046 //*-------- DEBUG LOG --------*/
2047 if (unlikely(LOG_LV_DEBUG ==
2048 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2049 std::stringstream buf;
2050 buf << "in_function: ";
2051 buf << "long int virtualservice_tcp::conv_ssl_option";
2052 buf << "(std::string opt_string): ";
2053 buf << "opt_string = " << opt_string;
2054 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 102, buf.str(),
2055 __FILE__, __LINE__);
2057 //*------ DEBUG LOG END ------*/
2061 // /usr/include/openssl/ssl.h
2062 // #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
2063 // #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
2064 // #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
2065 // #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
2066 // #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
2067 // #define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L
2068 // #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
2069 // #define SSL_OP_TLS_D5_BUG 0x00000100L
2070 // #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
2071 // #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L
2072 // #define SSL_OP_ALL 0x00000FF7L
2073 // #define SSL_OP_NO_QUERY_MTU 0x00001000L
2074 // #define SSL_OP_COOKIE_EXCHANGE 0x00002000L
2075 // #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
2076 // #define SSL_OP_SINGLE_ECDH_USE 0x00080000L
2077 // #define SSL_OP_SINGLE_DH_USE 0x00100000L
2078 // #define SSL_OP_EPHEMERAL_RSA 0x00200000L
2079 // #define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
2080 // #define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
2081 // #define SSL_OP_NO_SSLv2 0x01000000L
2082 // #define SSL_OP_NO_SSLv3 0x02000000L
2083 // #define SSL_OP_NO_TLSv1 0x04000000L
2084 // #define SSL_OP_PKCS1_CHECK_1 0x08000000L
2085 // #define SSL_OP_PKCS1_CHECK_2 0x10000000L
2086 // #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
2087 // #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
2088 if (opt_string == "SSL_OP_MICROSOFT_SESS_ID_BUG") {
2089 ret = SSL_OP_MICROSOFT_SESS_ID_BUG;
2090 } else if (opt_string == "SSL_OP_NETSCAPE_CHALLENGE_BUG") {
2091 ret = SSL_OP_NETSCAPE_CHALLENGE_BUG;
2092 } else if (opt_string == "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG") {
2093 ret = SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
2094 } else if (opt_string == "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG") {
2095 ret = SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
2096 } else if (opt_string == "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER") {
2097 ret = SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
2098 } else if (opt_string == "SSL_OP_MSIE_SSLV2_RSA_PADDING") {
2099 ret = SSL_OP_MSIE_SSLV2_RSA_PADDING;
2100 } else if (opt_string == "SSL_OP_SSLEAY_080_CLIENT_DH_BUG") {
2101 ret = SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
2102 } else if (opt_string == "SSL_OP_TLS_D5_BUG") {
2103 ret = SSL_OP_TLS_D5_BUG;
2104 } else if (opt_string == "SSL_OP_TLS_BLOCK_PADDING_BUG") {
2105 ret = SSL_OP_TLS_BLOCK_PADDING_BUG;
2106 } else if (opt_string == "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS") {
2107 ret = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
2108 } else if (opt_string == "SSL_OP_ALL") {
2109 // boost::asio::ssl::context::default_workarounds
2111 } else if (opt_string == "SSL_OP_NO_QUERY_MTU") {
2112 ret = SSL_OP_NO_QUERY_MTU;
2113 } else if (opt_string == "SSL_OP_COOKIE_EXCHANGE") {
2114 ret = SSL_OP_COOKIE_EXCHANGE;
2115 } else if (opt_string == "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION") {
2116 ret = SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
2117 } else if (opt_string == "SSL_OP_SINGLE_ECDH_USE") {
2118 ret = SSL_OP_SINGLE_ECDH_USE;
2119 } else if (opt_string == "SSL_OP_SINGLE_DH_USE") {
2120 // boost::asio::ssl::context::single_dh_use
2121 ret = SSL_OP_SINGLE_DH_USE;
2122 } else if (opt_string == "SSL_OP_EPHEMERAL_RSA") {
2123 ret = SSL_OP_EPHEMERAL_RSA;
2124 } else if (opt_string == "SSL_OP_CIPHER_SERVER_PREFERENCE") {
2125 ret = SSL_OP_CIPHER_SERVER_PREFERENCE;
2126 } else if (opt_string == "SSL_OP_TLS_ROLLBACK_BUG") {
2127 ret = SSL_OP_TLS_ROLLBACK_BUG;
2128 } else if (opt_string == "SSL_OP_NO_SSLv2") {
2129 // boost::asio::ssl::context::no_sslv2
2130 ret = SSL_OP_NO_SSLv2;
2131 } else if (opt_string == "SSL_OP_NO_SSLv3") {
2132 // boost::asio::ssl::context::no_sslv3
2133 ret = SSL_OP_NO_SSLv3;
2134 } else if (opt_string == "SSL_OP_NO_TLSv1") {
2135 // boost::asio::ssl::context::no_tlsv1
2136 ret = SSL_OP_NO_TLSv1;
2137 } else if (opt_string == "SSL_OP_PKCS1_CHECK_1") {
2138 ret = SSL_OP_PKCS1_CHECK_1;
2139 } else if (opt_string == "SSL_OP_PKCS1_CHECK_2") {
2140 ret = SSL_OP_PKCS1_CHECK_2;
2141 } else if (opt_string == "SSL_OP_NETSCAPE_CA_DN_BUG") {
2142 ret = SSL_OP_NETSCAPE_CA_DN_BUG;
2143 } else if (opt_string == "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG") {
2144 ret = SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
2146 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
2147 "ssl option string no match.",
2148 __FILE__, __LINE__);
2151 //*-------- DEBUG LOG --------*/
2152 if (unlikely(LOG_LV_DEBUG ==
2153 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2154 std::stringstream buf;
2155 buf << "out_function: ";
2156 buf << "long int virtualservice_tcp::conv_ssl_option";
2157 buf << "(std::string opt_string): ";
2158 buf << "return_value = " << ret;
2159 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 103, buf.str(),
2160 __FILE__, __LINE__);
2162 //------ DEBUG LOG END ------*/
2163 // if ret == -1 then No match.
2168 //! get ssl parameter
2169 //! @return get ssl parameter result
2170 bool l7vs::virtualservice_tcp::get_ssl_parameter()
2172 //*-------- DEBUG LOG --------*/
2173 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2174 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 104,
2175 "in_function: bool virtualservice_tcp::get_ssl_parameter()",
2176 __FILE__, __LINE__);
2178 //*------ DEBUG LOG END ------*/
2179 typedef std::vector< std::string > string_vector_type;
2182 string_vector_type string_vector;
2183 l7vs::error_code err;
2184 bool retbool = false;
2187 // param init ( ssl configuration file )
2188 if (unlikely(!param.init(l7vs::PARAM_COMP_SSL, ssl_file_name))) {
2189 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 24,
2190 "SSL config file read error.",
2191 __FILE__, __LINE__);
2195 //// SSL context parameter
2196 // Get parameter "ca_dir".
2197 ca_dir = param.get_string(l7vs::PARAM_COMP_SSL, "ca_dir",
2198 err, ssl_file_name);
2199 if (unlikely(err) || ca_dir == "") {
2200 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 9,
2201 "ca_dir parameter not found. Use default value.",
2202 __FILE__, __LINE__);
2203 ca_dir = DEFAULT_SSL_CA_DIR;
2206 // Get parameter "ca_file".
2207 ca_file = param.get_string(l7vs::PARAM_COMP_SSL, "ca_file",
2208 err, ssl_file_name);
2209 if (unlikely(err)) {
2210 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 25,
2211 "Cannot get ca_file parameter.",
2212 __FILE__, __LINE__);
2216 // Get parameter "cert_chain_dir".
2217 cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2221 if (unlikely(err) || cert_chain_dir == "") {
2222 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 10,
2223 "cert_chain_dir parameter not found. Use default value.",
2224 __FILE__, __LINE__);
2225 cert_chain_dir = DEFAULT_SSL_CERT_CHAIN_DIR;
2228 // Get parameter "cert_chain_file".
2229 cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
2233 if (unlikely(err) || cert_chain_file == "") {
2234 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 26,
2235 "Cannot get cert_chain_file parameter.",
2236 __FILE__, __LINE__);
2240 // Get parameter "private_key_dir".
2241 private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2245 if (unlikely(err) || private_key_dir == "") {
2246 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 11,
2247 "private_key_dir parameter not found. Use default value.",
2248 __FILE__, __LINE__);
2249 private_key_dir = DEFAULT_SSL_PRIVATE_KEY_DIR;
2252 // Get parameter "private_key_file".
2253 private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
2257 if (unlikely(err) || private_key_file == "") {
2258 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 27,
2259 "Cannot get private_key_file parameter.",
2260 __FILE__, __LINE__);
2264 // Get parameter "private_key_filetype".
2265 // and convert string to filetype define value.
2267 // /usr/include/openssl/ssl.h
2268 // #define SSL_FILETYPE_PEM X509_FILETYPE_PEM ->1
2269 // #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 ->2
2270 std::string filetype_str = param.get_string(
2271 l7vs::PARAM_COMP_SSL,
2272 "private_key_filetype",
2275 if (unlikely(err) || filetype_str == "") {
2276 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 12,
2277 "private_key_filetype parameter not found. Use default value.",
2278 __FILE__, __LINE__);
2279 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
2280 } else if (filetype_str == "SSL_FILETYPE_PEM") {
2281 private_key_filetype = boost::asio::ssl::context::pem;
2282 } else if (filetype_str == "SSL_FILETYPE_ASN1") {
2283 private_key_filetype = boost::asio::ssl::context::asn1;
2285 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
2286 "private_key_filetype convert error.",
2287 __FILE__, __LINE__);
2291 // Get parameter "private_key_passwd_dir".
2292 private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2293 "private_key_passwd_dir",
2296 if (unlikely(err) || private_key_passwd_dir == "") {
2297 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 13,
2298 "private_key_passwd_dir parameter not found. Use default value.",
2299 __FILE__, __LINE__);
2300 private_key_passwd_dir = DEFAULT_SSL_PRIVATE_KEY_PASSWD_DIR;
2303 // Get parameter "private_key_passwd_file".
2304 private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2305 "private_key_passwd_file",
2308 if (unlikely(err) || private_key_passwd_file == "") {
2309 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
2310 "Cannot get private_key_passwd_file parameter.",
2311 __FILE__, __LINE__);
2315 // Get parameter "verify_options".
2316 param.get_multistring(l7vs::PARAM_COMP_SSL,
2321 if (unlikely(err)) {
2322 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 14,
2323 "verify_options parameter not found. Use default value.",
2324 __FILE__, __LINE__);
2325 verify_options = DEFAULT_SSL_VERIFY_OPTIONS;
2327 // Make verify option bit data.
2328 for (string_vector_type::iterator itr = string_vector.begin();
2329 itr != string_vector.end(); ++itr) {
2330 // Convert string to define value.
2331 int int_val = conv_verify_option(*itr);
2332 if (unlikely(int_val == -1)) {
2333 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 30,
2334 "verify_options convert error.",
2335 __FILE__, __LINE__);
2338 verify_options = (verify_options | int_val);
2342 // Get parameter "verify_cert_depth".
2343 verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2344 "verify_cert_depth",
2347 if (unlikely(err)) {
2348 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 15,
2349 "verify_cert_depth parameter not found. Use default value.",
2350 __FILE__, __LINE__);
2351 verify_cert_depth = DEFAULT_SSL_VERIFY_CERT_DEPTH;
2352 } else if (unlikely(verify_cert_depth < 0 ||
2353 verify_cert_depth > INT_MAX)) {
2354 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 31,
2355 "Invalid verify_cert_depth parameter value.",
2356 __FILE__, __LINE__);
2360 // Get parameter "ssl_options".
2361 // and Check dh parameter file use or not.
2362 is_tmp_dh_use = false;
2363 param.get_multistring(l7vs::PARAM_COMP_SSL,
2368 if (unlikely(err)) {
2369 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 16,
2370 "ssl_options parameter not found. Use default value.",
2371 __FILE__, __LINE__);
2372 ssl_options = DEFAULT_SSL_OPTIONS;
2373 is_tmp_dh_use = true;
2375 // Make ssl option bit data.
2376 for (string_vector_type::iterator itr = string_vector.begin();
2377 itr != string_vector.end(); ++itr) {
2378 // Convert string to define value.
2379 long int longint_val = conv_ssl_option(*itr);
2380 if (unlikely(longint_val == -1)) {
2381 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 32,
2382 "ssl_options convert error.",
2383 __FILE__, __LINE__);
2385 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2386 is_tmp_dh_use = true;
2388 ssl_options = (ssl_options | longint_val);
2392 if (is_tmp_dh_use) {
2393 // Get parameter "tmp_dh_dir".
2394 tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2398 if (unlikely(err) || tmp_dh_dir == "") {
2399 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
2400 "tmp_dh_dir parameter not found. Use default value.",
2401 __FILE__, __LINE__);
2402 tmp_dh_dir = DEFAULT_SSL_TMP_DH_DIR;
2404 // Get parameter "tmp_dh_file".
2405 tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2409 if (unlikely(err) || tmp_dh_file == "") {
2410 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 33,
2411 "Cannot get tmp_dh_file parameter.",
2412 __FILE__, __LINE__);
2417 // Get parameter "cipher_list".
2418 cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2422 if (unlikely(err) || cipher_list == "") {
2423 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 18,
2424 "cipher_list parameter not found. Use default value.",
2425 __FILE__, __LINE__);
2426 cipher_list = DEFAULT_SSL_CIPHER_LIST;
2429 //// SSL session cache parameter
2430 // Get parameter "session_cache".
2431 is_session_cache_use = false;
2432 std::string cache_str = param.get_string(l7vs::PARAM_COMP_SSL,
2436 if (unlikely(err) || cache_str == "") {
2437 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
2438 "session_cache parameter not found. Use default value.",
2439 __FILE__, __LINE__);
2440 is_session_cache_use = true;
2441 } else if (cache_str == "on") {
2442 is_session_cache_use = true;
2443 } else if (cache_str == "off") {
2444 is_session_cache_use = false;
2446 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2447 "Invalid session_cache parameter value.", __FILE__, __LINE__);
2451 if (is_session_cache_use) {
2452 session_cache_mode = DEFAULT_SSL_SESSION_CACHE_MODE;
2453 // Get parameter "session_cache_size".
2454 session_cache_size = param.get_int(l7vs::PARAM_COMP_SSL,
2455 "session_cache_size",
2458 if (unlikely(err)) {
2459 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
2460 "session_cache_size parameter not found. Use default value.",
2461 __FILE__, __LINE__);
2462 session_cache_size = DEFAULT_SSL_SESSION_CACHE_SIZE;
2463 } else if (session_cache_size < 0 ||
2464 session_cache_size > INT_MAX) {
2465 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 35,
2466 "Invalid session_cache_size parameter value.", __FILE__, __LINE__);
2469 // Get parameter "session_cache_timeout".
2470 session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2471 "session_cache_timeout",
2474 if (unlikely(err)) {
2475 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
2476 "session_cache_timeout parameter not found. Use default value.",
2477 __FILE__, __LINE__);
2478 session_cache_timeout = DEFAULT_SSL_SESSION_CACHE_TIMEOUT;
2479 } else if (session_cache_timeout < 0 ||
2480 session_cache_timeout > INT_MAX) {
2481 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 36,
2482 "Invalid session_cache_timeout parameter value.",
2483 __FILE__, __LINE__);
2487 session_cache_mode = SSL_SESS_CACHE_OFF;
2490 //// SSL handshake timer parameter
2491 // Get parameter "timeout_sec".
2492 handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2496 if (unlikely(err)) {
2497 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2498 "timeout_sec parameter not found. Use default value.", __FILE__, __LINE__);
2499 handshake_timeout = DEFAULT_SSL_HANDSHAKE_TIMEOUT;
2500 } else if (handshake_timeout <= 0 || handshake_timeout > INT_MAX) {
2501 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 37,
2502 "Invalid timeout_sec parameter value.", __FILE__, __LINE__);
2512 //*-------- DEBUG LOG --------*/
2513 if (unlikely(LOG_LV_DEBUG ==
2514 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2515 std::stringstream buf;
2516 buf << "out_function: bool virtualservice_tcp::get_ssl_parameter(): ";
2517 buf << "ca_dir = " << ca_dir << ", ";
2518 buf << "ca_file = " << ca_file << ", ";
2519 buf << "cert_chain_dir = " << cert_chain_dir << ", ";
2520 buf << "cert_chain_file = " << cert_chain_file << ", ";
2521 buf << "private_key_dir = " << private_key_dir << ", ";
2522 buf << "private_key_file = " << private_key_file << ", ";
2523 buf << "private_key_filetype = " << private_key_filetype << ", ";
2524 buf << "private_key_passwd_dir = " << private_key_passwd_dir << ", ";
2525 buf << "private_key_passwd_file = " << private_key_passwd_file << ", ";
2526 buf << "verify_options = " << verify_options << ", ";
2527 buf << "verify_cert_depth = " << verify_cert_depth << ", ";
2528 buf << "ssl_options = " << ssl_options << ", ";
2529 if (is_tmp_dh_use) {
2530 buf << "tmp_dh_dir = " << tmp_dh_dir << ", ";
2531 buf << "tmp_dh_file = " << tmp_dh_file << ", ";
2533 buf << "cipher_list = " << cipher_list << ", ";
2534 buf << "session_cache_mode = " << session_cache_mode << ", ";
2535 if (is_session_cache_use) {
2536 buf << "session_cache_size = " << session_cache_size << ", ";
2537 buf << "session_cache_timeout = " << session_cache_timeout << ", ";
2539 buf << "handshake_timeout = " << handshake_timeout;
2540 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2542 __FILE__, __LINE__);
2544 //*------ DEBUG LOG END ------*/
2549 // set ssl context and ssl session cache configuration
2550 // @return set ssl config result
2551 bool l7vs::virtualservice_tcp::set_ssl_config()
2553 //*-------- DEBUG LOG --------*/
2554 if (unlikely(LOG_LV_DEBUG ==
2555 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2556 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 106,
2557 "in_function: bool virtualservice_tcp::set_ssl_config()",
2558 __FILE__, __LINE__);
2560 //*------ DEBUG LOG END ------*/
2562 bool retbool = false;
2565 //// SSL context setting.
2567 if (ca_file.size() == 0) {
2568 // specified CA path.
2570 sslcontext->add_verify_path(ca_dir);
2571 } catch (std::exception &e) {
2572 std::stringstream buf;
2573 buf << "Set root CA path error: " << e.what() << ".";
2574 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2576 __FILE__, __LINE__);
2580 // specified CA file.
2582 sslcontext->load_verify_file(ca_dir + ca_file);
2583 } catch (std::exception &e) {
2584 std::stringstream buf;
2585 buf << "Set root CA file error: " << e.what() << ".";
2586 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2588 __FILE__, __LINE__);
2593 // Set certificate chain file.
2595 sslcontext->use_certificate_chain_file(
2596 cert_chain_dir + cert_chain_file);
2597 } catch (std::exception &e) {
2598 std::stringstream buf;
2599 buf << "Set certificate chain file error: " << e.what() << ".";
2600 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2601 __FILE__, __LINE__);
2605 // Set password callback function.
2607 sslcontext->set_password_callback(
2608 boost::bind(&virtualservice_tcp::get_ssl_password, this));
2609 } catch (std::exception &e) {
2610 std::stringstream buf;
2611 buf << "Set password callback error: " << e.what() << ".";
2612 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2613 __FILE__, __LINE__);
2617 // Set private key file and filetype.
2619 sslcontext->use_private_key_file(
2620 private_key_dir + private_key_file, private_key_filetype);
2621 } catch (std::exception &e) {
2622 std::stringstream buf;
2623 buf << "Set private key file and filetype error: " << e.what() << ".";
2624 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2625 __FILE__, __LINE__);
2629 // Set verify options on the context.
2631 sslcontext->set_verify_mode(verify_options);
2632 } catch (std::exception &e) {
2633 std::stringstream buf;
2634 buf << "Set verify option error: " << e.what() << ".";
2635 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2636 __FILE__, __LINE__);
2640 // Set verify depth on the context.
2641 SSL_CTX_set_verify_depth(sslcontext->impl(), verify_cert_depth);
2643 // Set SSL options on the context.
2645 sslcontext->set_options(ssl_options);
2646 } catch (std::exception &e) {
2647 std::stringstream buf;
2648 buf << "Set SSL option error: " << e.what() << ".";
2649 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2650 __FILE__, __LINE__);
2654 // Set temporary Diffie-Hellman parameters file.
2655 if (is_tmp_dh_use) {
2657 sslcontext->use_tmp_dh_file(tmp_dh_dir + tmp_dh_file);
2658 } catch (std::exception &e) {
2659 std::stringstream buf;
2660 buf << "Set tmp DH file error: " << e.what() << ".";
2661 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2663 __FILE__, __LINE__);
2669 // Set cipher list on the context.
2670 if (unlikely(SSL_CTX_set_cipher_list(sslcontext->impl(),
2671 cipher_list.c_str()) != 1)) {
2672 std::stringstream buf;
2673 buf << "Set cipher list error.";
2674 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2676 __FILE__, __LINE__);
2680 //// SSL session cache setting.
2681 if (is_session_cache_use) {
2682 // Set session id context on the context.
2683 if (unlikely(SSL_CTX_set_session_id_context(
2685 (const unsigned char *)"ultramonkey", 11) != 1)) {
2686 std::stringstream buf;
2687 buf << "Set session id context error.";
2688 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2690 __FILE__, __LINE__);
2694 // Set session cache mode on the context.
2695 SSL_CTX_set_session_cache_mode(
2696 sslcontext->impl(), session_cache_mode);
2698 // Set session cache size on the context.
2699 SSL_CTX_sess_set_cache_size(sslcontext->impl(), session_cache_size);
2701 // Set session cache timeout on the context.
2702 SSL_CTX_set_timeout(sslcontext->impl(), session_cache_timeout);
2705 // session cache OFF.
2706 SSL_CTX_set_session_cache_mode(sslcontext->impl(),
2707 SSL_SESS_CACHE_OFF);
2715 //*-------- DEBUG LOG --------*/
2716 if (unlikely(LOG_LV_DEBUG ==
2717 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2718 std::stringstream buf;
2719 buf << "out_function: bool virtualservice_tcp::set_ssl_config(): ";
2720 get_ssl_config(buf);
2721 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 117, buf.str(),
2722 __FILE__, __LINE__);
2724 //*------ DEBUG LOG END ------*/
2729 // flush ssl session
2730 void l7vs::virtualservice_tcp::flush_ssl_session()
2732 // check expired cached sessions and do flushing
2733 // Need ssl_context lock?
2734 SSL_CTX_flush_sessions(sslcontext->impl(), time(0));
2738 // get ssl configuration form ssl context. (for debug)
2739 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream &buf)
2741 buf << "SSL configuration information: ";
2742 buf << "Verify mode[" << SSL_CTX_get_verify_mode(sslcontext->impl()) << "] ";
2743 buf << "Verify depth[" << SSL_CTX_get_verify_depth(sslcontext->impl()) << "] ";
2744 buf << "SSL options[" << SSL_CTX_get_options(sslcontext->impl()) << "] ";
2745 buf << "Cache mode[" << SSL_CTX_get_session_cache_mode(sslcontext->impl()) << "] ";
2746 buf << "Cache size[" << SSL_CTX_sess_get_cache_size(sslcontext->impl()) << "] ";
2747 buf << "Cache timeout[" << SSL_CTX_get_timeout(sslcontext->impl()) << "] ";
2751 // get ssl session cache information form ssl context. (for debug)
2752 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream &buf)
2754 buf << "SSL session cache information: ";
2755 buf << "Session number[" << SSL_CTX_sess_number(sslcontext->impl()) << "] ";
2756 buf << "Accept[" << SSL_CTX_sess_accept(sslcontext->impl()) << "] ";
2757 buf << "Accept good[" << SSL_CTX_sess_accept_good(sslcontext->impl()) << "] ";
2758 buf << "Accept renegotiate[" << SSL_CTX_sess_accept_renegotiate(sslcontext->impl()) << "] ";
2759 buf << "Hits[" << SSL_CTX_sess_hits(sslcontext->impl()) << "] ";
2760 buf << "Misses[" << SSL_CTX_sess_misses(sslcontext->impl()) << "] ";
2761 buf << "Timeouts[" << SSL_CTX_sess_timeouts(sslcontext->impl()) << "] ";
2762 buf << "Cache full[" << SSL_CTX_sess_cache_full(sslcontext->impl()) << "] ";