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>
34 #include "virtualservice.h"
35 #include "logger_enum.h"
37 #include "parameter.h"
38 #include "snmpagent.h"
40 #include "logger_access_manager.h"
42 // implementation for virtualservice_tcp
44 * virtualservice_tcp class constructor.
46 l7vs::virtualservice_tcp::virtualservice_tcp(const l7vsd &invsd,
47 const replication &inrep,
48 const virtualservice_element &inelement)
50 virtualservice_base(invsd, inrep, inelement)
52 access_log_file_name = "";
53 dispatcher.reset(new boost::asio::io_service(10));
54 calc_bps_timer.reset(new boost::asio::deadline_timer(*dispatcher));
55 replication_timer.reset(new boost::asio::deadline_timer(*dispatcher));
56 protomod_rep_timer.reset(new boost::asio::deadline_timer(*dispatcher));
57 schedmod_rep_timer.reset(new boost::asio::deadline_timer(*dispatcher));
58 acceptor_.reset(new boost::asio::ip::tcp::acceptor(*dispatcher));
59 sslcontext.reset(new boost::asio::ssl::context(*dispatcher, DEFAULT_SSL_METHOD));
66 private_key_file = "";
67 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
68 private_key_passwd_dir = "";
69 private_key_passwd_file = "";
71 verify_cert_depth = 0;
73 is_tmp_dh_use = false;
77 is_session_cache_use = false;
78 session_cache_mode = 0;
79 session_cache_size = 0;
80 session_cache_timeout = 0;
81 handshake_timeout = 0;
84 * virtualservice_tcp class destructor.
86 l7vs::virtualservice_tcp::~virtualservice_tcp()
90 * replication interrupt event
95 void l7vs::virtualservice_tcp::handle_replication_interrupt(const boost::system::error_code &err)
97 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
98 boost::format fmt("in_function: void virtualservice_tcp::handle_replication_interrupt( "
99 "const boost::system::error_code& err ): err = %s, err.message = %s");
100 fmt % (err ? "true" : "false") % err.message();
101 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 20, fmt.str(), __FILE__, __LINE__);
106 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, err.message(), __FILE__, __LINE__);
110 interrupt_running_flag++;
113 replication &rep_noconst = const_cast<replication &>(rep);
115 if (replication::REPLICATION_SINGLE == rep_noconst.get_status()) {
116 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "replication mode is single.",
118 interrupt_running_flag--;
122 std::stringstream tmp_tcp_ep;
123 tmp_tcp_ep << element.tcp_accept_endpoint;
124 std::stringstream tmp_udp_ep;
125 tmp_udp_ep << element.udp_recv_endpoint;
126 std::stringstream tmp_sorry_ep;
127 tmp_sorry_ep << element.sorry_endpoint;
129 //get replication area
130 unsigned int rep_size = 0;
131 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
132 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
133 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
134 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, REP_BLOCK_SIZE_ERR_MSG,
136 interrupt_running_flag--;
140 //check max data size
141 if ((rep_size * DATA_SIZE) <
142 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
143 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, REP_AREA_SIZE_ERR_MSG,
145 interrupt_running_flag--;
149 //lock replication area
150 rep_noconst.lock(REP_AREA_NAME);
152 //read header value and set loop count
153 unsigned int loop_cnt = rep_header_ptr->data_num;
154 //if data_num over MAX_REPLICATION_DATA_NUM, data_num = 0
155 if (static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt) {
159 //set start pointer(pointer of replication_data)
160 replication_data *rep_data_ptr = reinterpret_cast<replication_data *>(++rep_header_ptr);
163 for (unsigned int i = 0; i < loop_cnt; ++i) {
164 //check equal udpmode and tcp_accept_endpoint
165 if ((rep_data_ptr->udpmode == element.udpmode) &&
166 (0 == strncmp(rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 47))) {
170 //increment data pointer
174 //if it is new data, increment data num.
176 rep_header_ptr = reinterpret_cast<replication_header *>(
177 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
178 ++(rep_header_ptr->data_num);
180 //write replication data
181 rep_data_ptr->udpmode = element.udpmode;
182 strncpy(rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 48);
183 strncpy(rep_data_ptr->udp_endpoint, tmp_udp_ep.str().c_str(), 48);
184 rep_data_ptr->sorry_maxconnection = element.sorry_maxconnection;
185 strncpy(rep_data_ptr->sorry_endpoint, tmp_sorry_ep.str().c_str(), 48);
186 rep_data_ptr->sorry_flag = element.sorry_flag;
187 rep_data_ptr->sorry_fwdmode = element.sorry_fwdmode;
188 rep_data_ptr->qos_up = element.qos_upstream;
189 rep_data_ptr->qos_down = element.qos_downstream;
191 //unlock replication area
192 rep_noconst.unlock(REP_AREA_NAME);
194 if (0 == virtualservice_stop_flag.get()) {
195 //register handle_replication_interrupt
196 replication_timer->expires_from_now(
197 boost::posix_time::milliseconds(param_data.rep_interval));
198 replication_timer->async_wait(boost::bind(
199 &virtualservice_tcp::handle_replication_interrupt,
200 this, boost::asio::placeholders::error));
202 interrupt_running_flag--;
204 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
205 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
206 "out_function: void virtualservice_tcp::handle_replication_interrupt( "
207 "const boost::system::error_code& err )", __FILE__, __LINE__);
212 * read replication data
214 * @param read_replicationdata
218 void l7vs::virtualservice_tcp::read_replicationdata()
220 Logger funclog(LOG_CAT_L7VSD_VIRTUALSERVICE, 22, "function: "
221 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
223 replication &rep_noconst = const_cast<replication &>(rep);
225 if (replication::REPLICATION_SINGLE == rep_noconst.get_status()) {
226 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, "replication mode is single.",
231 unsigned int rep_size = 0;
232 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
233 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
234 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
235 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 3, REP_BLOCK_SIZE_ERR_MSG,
237 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
238 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 23, "out_function: "
239 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
244 //check max data size
245 if ((rep_size * DATA_SIZE) <
246 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
247 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 4, REP_AREA_SIZE_ERR_MSG,
249 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
250 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 24, "out_function: "
251 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
255 //lock replication area
256 rep_noconst.lock(REP_AREA_NAME);
258 //read header value and set loop count
259 unsigned int loop_cnt = rep_header_ptr->data_num;
260 //if data_num over MAX_REPLICATION_DATA_NUM, set data_num = 0
261 if (static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt) {
262 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 5, REP_BLOCK_SIZE_ERR_MSG,
264 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
265 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 25, "out_function: "
266 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
268 rep_header_ptr->data_num = 0;
269 rep_noconst.unlock(REP_AREA_NAME);
273 //set start pointer(pointer of replication_data)
274 replication_data *rep_data_ptr = reinterpret_cast<replication_data *>(++rep_header_ptr);
277 for (unsigned int i = 0; i < loop_cnt; ++i) {
278 //get tcp endpoint data
279 std::string tmpstr = rep_data_ptr->tcp_endpoint;
281 unsigned short portno;
283 portno = boost::lexical_cast<unsigned short>(tmpstr.substr((tmpstr.rfind(":") + 1)));
284 } catch (const boost::bad_lexical_cast &err) {
287 if (tmpstr[0] == '[') {
289 ipaddr = tmpstr.substr(1, (tmpstr.rfind("]") - 1));
292 ipaddr = tmpstr.substr(0, tmpstr.rfind(":"));
294 //check equal udpmode and tcp_accept_endpoint
295 if ((rep_data_ptr->udpmode == element.udpmode) &&
296 (tcp_endpoint_type(boost::asio::ip::address::from_string(ipaddr), portno)
297 == element.tcp_accept_endpoint)) {
298 element.sorry_maxconnection = rep_data_ptr->sorry_maxconnection;
299 tmpstr = rep_data_ptr->sorry_endpoint;
301 portno = boost::lexical_cast<unsigned short>(
302 tmpstr.substr((tmpstr.rfind(":") + 1)));
303 } catch (const boost::bad_lexical_cast &err) {
306 if (tmpstr[0] == '[') {
308 ipaddr = tmpstr.substr(1, (tmpstr.rfind("]") - 1));
311 ipaddr = tmpstr.substr(0, tmpstr.rfind(":"));
313 element.sorry_endpoint =
314 tcp_endpoint_type(boost::asio::ip::address::from_string(ipaddr), portno);
315 element.sorry_flag = rep_data_ptr->sorry_flag;
316 element.sorry_fwdmode = (virtualservice_element::SORRYSERVER_FWDMODE_TAG)(rep_data_ptr->sorry_fwdmode);
317 element.qos_upstream = rep_data_ptr->qos_up;
318 element.qos_downstream = rep_data_ptr->qos_down;
321 //increment data pointer
325 //unlock replication area
326 rep_noconst.unlock(REP_AREA_NAME);
328 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
329 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 26, "out_function: "
330 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
337 * @param handle_accept
341 void l7vs::virtualservice_tcp::handle_accept(const l7vs::session_thread_control *stc_ptr, const boost::system::error_code &err)
343 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
344 boost::format fmt("in_function: void virtualservice_tcp::handle_accept( "
345 "const boost::shared_ptr<session_thread_control> , "
346 "const boost::system::error_code& err ): err = %s, err.message = %s");
347 fmt % (err ? "true" : "false") % err.message();
348 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 27, fmt.str(), __FILE__, __LINE__);
351 if (unlikely(virtualservice_stop_flag.get())) {
356 boost::mutex::scoped_lock lock(adm_cmd_wait_flag_mutex);
357 if (unlikely(adm_cmd_wait_flag)){
358 adm_cmd_wait_flag_cond.wait(lock);
362 session_thread_control *stc_ptr_noconst = const_cast<session_thread_control *>(stc_ptr);
364 if (unlikely(err == boost::asio::error::operation_aborted)) { // nomal exit case
365 boost::format fmt("Thread ID[%d] handle accept cancel : %s");
366 fmt % boost::this_thread::get_id() % err.message();
367 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 0, fmt.str(), __FILE__, __LINE__);
369 } else if (unlikely(err)) { // register next accept handle when error mode.
370 if (!ssl_virtualservice_mode_flag) {
371 waiting_session->get_client_socket().get_socket().close();
372 acceptor_->async_accept(waiting_session->get_client_socket().get_socket(),
373 boost::bind(&virtualservice_tcp::handle_accept,
376 boost::asio::placeholders::error));
378 waiting_session->get_client_ssl_socket().lowest_layer().close();
379 acceptor_->async_accept(waiting_session->get_client_ssl_socket().lowest_layer(),
380 boost::bind(&virtualservice_tcp::handle_accept,
383 boost::asio::placeholders::error));
385 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, err.message(), __FILE__, __LINE__);
389 tcp_session *tmp_session = stc_ptr_noconst->get_session().get();
391 if (ssl_file_name != "") {
393 //*-------- DEBUG LOG --------*/
394 if (unlikely(LOG_LV_DEBUG ==
395 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
396 std::stringstream buf;
397 buf << "virtualservice_tcp::handle_accept(): ";
398 buf << "ssl session cache flush before: ";
399 get_ssl_session_cache_info(buf);
400 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
404 //*------ DEBUG LOG END ------*/
406 // ssl session cache flush
407 if (is_session_cache_use == true) {
408 long ssl_cache_num = SSL_CTX_sess_number(sslcontext->impl());
409 if (ssl_cache_num >= session_cache_size) {
414 //*-------- DEBUG LOG --------*/
415 if (unlikely(LOG_LV_DEBUG ==
416 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
417 std::stringstream buf;
418 buf << "virtualservice_tcp::handle_accept(): ";
419 buf << "ssl session cache flush after: ";
420 get_ssl_session_cache_info(buf);
421 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
425 //*------ DEBUG LOG END ------*/
428 // initialize session
429 stc_ptr_noconst->get_session()->initialize();
431 // send access log output ON or OFF message to tcp_session
432 stc_ptr_noconst->session_access_log_output_mode_change(access_log_flag);
434 active_sessions.insert(tmp_session, stc_ptr_noconst);
436 //check sorry flag and status
438 (0 != element.sorry_flag) ||
439 ((0 < element.sorry_maxconnection) && ((active_count.get() >= static_cast<size_t>(element.sorry_maxconnection)))
442 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
443 boost::format fmt("Connection switch Sorry mode. "
444 "active_session.size = %d, active_count.get = %d");
445 fmt % active_sessions.size() % active_count.get();
446 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 30, fmt.str(), __FILE__, __LINE__);
449 stc_ptr_noconst->get_session()->set_virtual_service_message(tcp_session::SORRY_STATE_ENABLE, boost::asio::ip::tcp::endpoint());
452 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
453 boost::format fmt1("active session thread id = %d");
454 fmt1 % stc_ptr_noconst->get_upthread_id();
455 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 31, fmt1.str(), __FILE__, __LINE__);
456 boost::format fmt2("pool_session.size = %d");
457 fmt2 % pool_sessions.size();
458 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 32, fmt2.str(), __FILE__, __LINE__);
459 boost::format fmt3("active_session.size = %d");
460 fmt3 % active_sessions.size();
461 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 33, fmt3.str(), __FILE__, __LINE__);
462 boost::format fmt4("active_count = %d");
463 fmt4 % active_count.get();
464 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 34, fmt4.str(), __FILE__, __LINE__);
467 stc_ptr_noconst->startupstream();
468 stc_ptr_noconst->startdownstream();
470 //left session is less than the threshold
471 if ((sessionpool_alert_flag == false) &&
472 ((pool_sessions.size() + 1) < param_data.session_pool_alert_on)) {
473 //create trap message
474 trapmessage trap_msg;
475 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
476 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
478 //push the trap message
479 snmpagent::push_trapmessage(trap_msg, err_code);
481 std::string str("Push trap message failed :");
482 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 38, str , __FILE__, __LINE__);
484 //set sessionpool alert flag true
485 sessionpool_alert_flag = true;
488 //waiting, pool_sessions.size become over 1
489 //pick up session from pool
490 session_thread_control *stc_ptr_register_accept;
493 stc_ptr_register_accept = pool_sessions.pop();
494 if (stc_ptr_register_accept) break;
495 else if (pool_sessions.empty()) dispatcher->poll();
496 timespec ts = { 0, 50 };
497 nanosleep(&ts, NULL);
500 //session add wait_sessions
501 boost::mutex::scoped_lock up_wait_lk(stc_ptr_register_accept->get_upthread_mutex());
502 boost::mutex::scoped_lock down_wait_lk(stc_ptr_register_accept->get_downthread_mutex());
504 waiting_session = stc_ptr_register_accept->get_session().get();
506 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
507 boost::format fmt1("active session thread id = %d");
508 fmt1 % stc_ptr_register_accept->get_upthread_id();
509 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 35, fmt1.str(), __FILE__, __LINE__);
510 boost::format fmt2("pool_session.size = %d");
511 fmt2 % pool_sessions.size();
512 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 36, fmt2.str(), __FILE__, __LINE__);
513 boost::format fmt3("active_session.size = %d");
514 fmt3 % active_sessions.size();
515 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 37, fmt3.str(), __FILE__, __LINE__);
516 boost::format fmt4("active_count = %d");
517 fmt4 % active_count.get();
518 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 38, fmt4.str(), __FILE__, __LINE__);
521 //register accept event handler
522 if (!ssl_virtualservice_mode_flag) {
523 acceptor_->async_accept(waiting_session->get_client_socket().get_socket(),
524 boost::bind(&virtualservice_tcp::handle_accept,
526 stc_ptr_register_accept,
527 boost::asio::placeholders::error));
529 acceptor_->async_accept(waiting_session->get_client_ssl_socket().lowest_layer(),
530 boost::bind(&virtualservice_tcp::handle_accept,
532 stc_ptr_register_accept,
533 boost::asio::placeholders::error));
536 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
537 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 39,
539 "void virtualservice_tcp::handle_accept( "
540 "const boost::shared_ptr<session_thread_control> , "
541 "const boost::system::error_code& err )", __FILE__, __LINE__);
546 * initialize virtualservice(TCP)
551 void l7vs::virtualservice_tcp::initialize(l7vs::error_code &err)
553 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
554 boost::format formatter("in_function: void virtualservice_tcp::initialize( "
555 "l7vs::error_code& err )");
556 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, formatter.str(), __FILE__, __LINE__);
558 if (pool_sessions.size() != 0) {
559 err.setter(true, "VirtualService already initialized.");
560 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
561 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
562 "l7vs::error_code& err ): err = %s, err.message = %s");
563 formatter % (err ? "true" : "false") % err.get_message();
564 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 41, formatter.str(),
570 //load parameter value
573 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
574 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
575 "l7vs::error_code& err ): err = %s, err.message = %s");
576 formatter % (err ? "true" : "false") % err.get_message();
577 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 42, formatter.str(),
583 // access log flag and access log file name setting contents check.
584 if (element.access_log_flag == 1 && element.access_log_file_name == "") {
585 boost::format formatter("access log file name not set error");
586 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 3, formatter.str(), __FILE__, __LINE__);
587 err.setter(true, "access log file name not set error");
591 logger_implement_access *access_log_instance = NULL;
592 // access log instance create.
593 if (element.access_log_file_name != "") {
595 = logger_access_manager::getInstance().find_logger_implement_access(
596 element.access_log_file_name,
597 element.access_log_rotate_arguments,
599 if (access_log_instance == NULL) {
600 boost::format formatter("access logger Instance acquisition err = %s, "
601 "err.message = %s ");
602 formatter % (err ? "true" : "false") % err.get_message();
603 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 4, formatter.str(),
605 err.setter(true, "access log class instance create failed");
611 boost::asio::ip::address address = element.tcp_accept_endpoint.address();
612 #ifdef SCHED_SETAFFINITY
613 vsnic_cpumask = get_cpu_mask(address);
614 rsnic_cpumask = get_cpu_mask(param_data.nic_realserver_side);
618 boost::system::error_code acceptor_err;
619 acceptor_->open(element.tcp_accept_endpoint.protocol(), acceptor_err);
621 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 5, acceptor_err.message(),
623 err.setter(true, acceptor_err.message());
626 acceptor_->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), acceptor_err);
628 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 6, acceptor_err.message(),
630 err.setter(true, acceptor_err.message());
633 if (likely(address.is_v6())) {
634 boost::asio::ip::v6_only option(true);
635 acceptor_->set_option(option, acceptor_err);
637 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 7, acceptor_err.message(),
639 err.setter(true, acceptor_err.message());
643 acceptor_->bind(element.tcp_accept_endpoint, acceptor_err);
645 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 8, acceptor_err.message(),
647 err.setter(true, acceptor_err.message());
651 //read replication data
652 read_replicationdata();
654 //load protocol module
655 protomod = protocol_module_control::getInstance().load_module(element.protocol_module_name);
656 if (NULL == protomod) {
658 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 9, PROTOMOD_LOAD_ERROR_MSG,
660 err.setter(true, PROTOMOD_LOAD_ERROR_MSG);
661 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
662 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
663 "l7vs::error_code& err ): err = %s, err.message = %s");
664 formatter % (err ? "true" : "false") % err.get_message();
665 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 43, formatter.str(),
670 //Protocol Module Initialize
671 protomod->init_logger_functions(
672 boost::bind(&Logger::getLogLevel, LOG_CAT_PROTOCOL),
673 boost::bind(&Logger::putLogFatal, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
674 boost::bind(&Logger::putLogError, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
675 boost::bind(&Logger::putLogWarn, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
676 boost::bind(&Logger::putLogInfo, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
677 boost::bind(&Logger::putLogDebug, LOG_CAT_PROTOCOL, _1, _2, _3, _4));
678 protomod->initialize(
679 boost::bind(&virtualservice_tcp::rs_list_begin, this),
680 boost::bind(&virtualservice_tcp::rs_list_end, this),
681 boost::bind(&virtualservice_tcp::rs_list_next, this, _1),
682 boost::bind(&virtualservice_tcp::rs_list_lock, this),
683 boost::bind(&virtualservice_tcp::rs_list_unlock, this));
684 protomod->init_replication_functions(
685 boost::bind(&virtualservice_tcp::replication_pay_memory, this, _1, _2),
686 boost::bind(&virtualservice_tcp::replication_area_lock, this, element.protocol_module_name),
687 boost::bind(&virtualservice_tcp::replication_area_unlock, this, element.protocol_module_name),
688 element.tcp_accept_endpoint,
689 element.udp_recv_endpoint);
690 tcp_schedule_func_type sched_rs_func = boost::bind(
691 &virtualservice_tcp::schedule_rs, this, _1, _2, _3, _4, _5);
692 protomod->register_schedule(sched_rs_func);
694 protocol_module_base::check_message_result pm_result;
696 pm_result = protomod->check_parameter(element.protocol_args);
697 if (!pm_result.flag) {
698 err.setter(true, "Protocol Module argument error.");
699 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
700 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
701 "l7vs::error_code& err ): err = %s, err.message = %s");
702 formatter % (err ? "true" : "false") % err.get_message();
703 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 44, formatter.str(),
708 pm_result = protomod->set_parameter(element.protocol_args);
709 if (!pm_result.flag) {
710 err.setter(true, "Protocol Module argument error.");
711 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
712 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
713 "l7vs::error_code& err ): err = %s, err.message = %s");
714 formatter % (err ? "true" : "false") % err.get_message();
715 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 45, formatter.str(),
721 protomod->get_option_info(protocol_module_for_indication_options);
722 element.protocol_module_for_indication_options = protocol_module_for_indication_options;
724 //load schedule module
725 schedmod = schedule_module_control::getInstance().load_module(element.schedule_module_name);
726 if (NULL == schedmod) {
728 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 10, SCHEDMOD_LOAD_ERROR_MSG,
730 err.setter(true, SCHEDMOD_LOAD_ERROR_MSG);
731 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
732 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
733 "l7vs::error_code& err ) : err = %s, err.message = %s");
734 formatter % (err ? "true" : "false") % err.get_message();
735 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 46, formatter.str(),
740 //Schedule Module Initialize
741 schedmod->init_logger_functions(
742 boost::bind(&Logger::getLogLevel, LOG_CAT_SCHEDULE),
743 boost::bind(&Logger::putLogFatal, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
744 boost::bind(&Logger::putLogError, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
745 boost::bind(&Logger::putLogWarn, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
746 boost::bind(&Logger::putLogInfo, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
747 boost::bind(&Logger::putLogDebug, LOG_CAT_SCHEDULE, _1, _2, _3, _4));
748 schedmod->initialize();
749 schedmod->init_replication_functions(
750 boost::bind(&virtualservice_tcp::replication_pay_memory, this, _1, _2),
751 boost::bind(&virtualservice_tcp::replication_area_lock, this, element.schedule_module_name),
752 boost::bind(&virtualservice_tcp::replication_area_unlock, this, element.schedule_module_name),
753 element.tcp_accept_endpoint,
754 element.udp_recv_endpoint);
756 // access log flag set
757 access_log_flag = false;
758 if (element.access_log_flag == 1) {
759 access_log_flag = true;
762 // access log rotation information set.
763 if (element.access_log_rotate_key_info == "") {
764 element.access_log_rotate_key_info = "none";
765 element.access_log_rotate_verbose_info = logger_access_manager::getInstance().get_rotate_default_verbose_displayed_contents();
767 element.access_log_rotate_verbose_info = element.access_log_rotate_key_info;
769 access_log_file_name = element.access_log_file_name;
770 access_log_rotate_arguments = element.access_log_rotate_arguments;
773 ssl_virtualservice_mode_flag = false;
774 ssl_file_name = element.ssl_file_name;
775 if (ssl_file_name != "") {
776 ssl_file_name = element.ssl_file_name;
778 if (unlikely(!get_ssl_parameter())) {
780 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 11, "get ssl parameter failed",
782 err.setter(true, "get ssl parameter failed");
785 // set SSL configuration
786 if (unlikely(!set_ssl_config())) {
788 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 12, "set ssl config failed",
790 err.setter(true, "set ssl config failed");
793 ssl_virtualservice_mode_flag = true;
799 //create session pool
801 int session_pool_size;
802 if (element.session_thread_pool_size > 0) {
803 session_pool_size = element.session_thread_pool_size;
805 session_pool_size = param_data.session_pool_size;
807 for (int i = 0; i < session_pool_size; ++i) {
809 tcp_session *sess = new tcp_session(*this,
812 element.tcp_accept_endpoint,
813 ssl_virtualservice_mode_flag,
815 is_session_cache_use,
817 access_log_instance);
818 session_result_message result = sess->initialize();
819 if (result.flag == true) {
820 err.setter(result.flag, result.message);
821 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
822 boost::format formatter("out_function: "
823 "void virtualservice_tcp::initialize( "
824 "l7vs::error_code& err ): err = %s, "
826 formatter % (err ? "true" : "false") % err.get_message();
827 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 47,
828 formatter.str(), __FILE__, __LINE__);
832 session_thread_control *p_stc = new session_thread_control(
833 sess, vsnic_cpumask, rsnic_cpumask, -1);
835 p_stc->start_thread();
836 while (!pool_sessions.push(p_stc)) {}
839 LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "error, create session.",
842 err.setter(true, "error, create session.");
845 l7vs::error_code finalize_err;
846 finalize_err.setter(false, "");
847 finalize(finalize_err);
849 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
850 boost::format formatter("out_function: "
851 "void virtualservice_tcp::initialize( "
852 "l7vs::error_code& err ): err = %s, err.message = %s");
853 formatter % (err ? "true" : "false") % err.get_message();
854 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 48, formatter.str(),
860 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
861 boost::format fmt1("pool_session.size = %d");
862 fmt1 % pool_sessions.size();
863 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 49, fmt1.str(),
865 boost::format fmt2("active_session.size = %d");
866 fmt2 % active_sessions.size();
867 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 50, fmt2.str(),
872 err.setter(false, "");
874 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
875 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
876 "l7vs::error_code& err ): err = %s, err.message = %s");
877 formatter % (err ? "true" : "false") % err.get_message();
878 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 51, formatter.str(),
884 * finalize virtualservice(TCP)
889 void l7vs::virtualservice_tcp::finalize(l7vs::error_code &err)
891 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
892 boost::format formatter("in_function: void virtualservice_tcp::finalize( "
893 "l7vs::error_code& err )");
894 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 52, formatter.str(),
896 boost::format fmt1("pool_session.size = %d");
897 fmt1 % pool_sessions.size();
898 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 53, fmt1.str(),
900 boost::format fmt2("active_session.size = %d");
901 fmt2 % active_sessions.size();
902 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 54, fmt2.str(),
906 //release sessions[i]->join();
907 while (!pool_sessions.empty()) {
908 session_thread_control *stc = pool_sessions.pop();
911 boost::mutex::scoped_lock upthread_wait(stc->get_upthread_mutex());
912 boost::mutex::scoped_lock downthread_wait(stc->get_downthread_mutex());
916 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
917 boost::format fmt("join pool session: pool_sessions.size = %d");
918 fmt % pool_sessions.size();
919 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 55, fmt.str(),
923 //waiting session delete
924 delete waiting_session;
925 waiting_session = NULL;
927 //unload ProtocolModule
929 //finalize ProtocolModule
930 protomod->finalize();
931 //unload ProtocolModule
932 protocol_module_control::getInstance().unload_module(protomod);
935 //unload ScheduleModule
937 schedule_module_control::getInstance().unload_module(schedmod);
941 active_sessions.clear();
942 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
943 boost::format fmt1("pool_session.size = %d");
944 fmt1 % pool_sessions.size();
945 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 56, fmt1.str(), __FILE__, __LINE__);
946 boost::format fmt2("active_session.size = %d");
947 fmt2 % active_sessions.size();
948 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 57, fmt2.str(), __FILE__, __LINE__);
951 //clear replication_data
952 bool replication_status = true;
953 replication &rep_noconst = const_cast<replication &>(rep);
955 if (replication::REPLICATION_SINGLE != rep_noconst.get_status()) {
956 unsigned int rep_size = 0;
957 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
958 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
959 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
960 err.setter(true, REP_BLOCK_SIZE_ERR_MSG);
961 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 6, REP_BLOCK_SIZE_ERR_MSG,
963 replication_status = false;
966 //check max data size
967 if ((rep_size * DATA_SIZE) <
968 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
969 err.setter(true, REP_AREA_SIZE_ERR_MSG);
970 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 7, REP_AREA_SIZE_ERR_MSG,
972 replication_status = false;
974 if ((NULL != rep_header_ptr) && (replication_status)) {
975 //lock replication area
976 rep_noconst.lock(REP_AREA_NAME);
978 rep_header_ptr->data_num = 0;
979 //unlock replication area
980 rep_noconst.unlock(REP_AREA_NAME);
984 //vsd.release_virtual_service( element );
985 if (access_log_file_name != "") {
986 // erase access log instance.
987 logger_access_manager::getInstance().erase_logger_implement_access(access_log_file_name, err);
989 boost::format fmt("access logger instance erase err:%s");
990 fmt % err.get_message();
991 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 8,
997 vsd.release_virtual_service(element);
999 err.setter(false, "");
1001 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1002 boost::format formatter("out_function: void virtualservice_tcp::finalize( "
1003 "l7vs::error_code& err ): err = %s, err.message = %s");
1004 formatter % (err ? "true" : "false") % err.get_message();
1005 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 58, formatter.str(), __FILE__, __LINE__);
1011 * equal compare virtualservice(TCP)
1013 * @param virtualservice_base
1014 * @return bool ( true = equal )
1016 bool l7vs::virtualservice_tcp::operator==(const l7vs::virtualservice_base &in)
1018 boost::format formatter("function: void virtualservice_tcp::operator==( "
1019 "const l7vs::virtualservice_base& in )");
1020 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 59, formatter.str(), __FILE__, __LINE__);
1022 virtualservice_base &vs = const_cast<virtualservice_base &>(in);
1023 return ((element.tcp_accept_endpoint == vs.get_element().tcp_accept_endpoint)
1024 && (element.udpmode == vs.get_element().udpmode));
1028 * not-equal compare virtualservice(TCP)
1030 * @param virtualservice_base
1031 * @return bool ( true = not-equal )
1033 bool l7vs::virtualservice_tcp::operator!=(const l7vs::virtualservice_base &in)
1035 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1036 boost::format formatter("in/out_function: void virtualservice_tcp::operator!=( "
1037 "const l7vs::virtualservice_base& in )");
1038 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 60, formatter.str(), __FILE__, __LINE__);
1040 virtualservice_base &vs = const_cast<virtualservice_base &>(in);
1041 return ((element.tcp_accept_endpoint != vs.get_element().tcp_accept_endpoint)
1042 || (element.udpmode != vs.get_element().udpmode));
1046 * add VirtualService( not-implement )
1048 * @param virtualservice_element
1052 void l7vs::virtualservice_tcp::set_virtualservice(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1054 err.setter(false, "");
1058 * edit VirtualService
1060 * @param virtualservice_element
1064 void l7vs::virtualservice_tcp::edit_virtualservice(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1066 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1067 boost::format formatter("in_function: void virtualservice_tcp::edit_virtualservice( "
1068 "const l7vs::virtualservice_element& in,"
1069 "l7vs::error_code& err ): dump in ");
1070 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 61, formatter.str(), __FILE__, __LINE__);
1073 virtualservice_element &elem = const_cast<virtualservice_element &>(in);
1074 if ((element.udpmode != elem.udpmode) ||
1075 (element.tcp_accept_endpoint != elem.tcp_accept_endpoint) ||
1076 (element.protocol_module_name != elem.protocol_module_name)) {
1077 err.setter(true, "Virtual Service does not exist.");
1078 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1079 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1080 "const l7vs::virtualservice_element& in,"
1081 "l7vs::error_code& err ): err = %s, err.message = %s");
1082 formatter % (err ? "true" : "false") % err.get_message();
1083 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 62, formatter.str(),
1084 __FILE__, __LINE__);
1089 //if change ScheduleModule Name, unload old ScheduleModule and load new ScheduleModule
1090 if ((element.schedule_module_name != elem.schedule_module_name) && ("" != elem.schedule_module_name)) {
1091 schedule_module_control::getInstance().unload_module(schedmod);
1092 schedmod = schedule_module_control::getInstance().load_module(elem.schedule_module_name);
1093 if (NULL == schedmod) {
1095 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 13, SCHEDMOD_LOAD_ERROR_MSG,
1096 __FILE__, __LINE__);
1097 err.setter(true, SCHEDMOD_LOAD_ERROR_MSG);
1098 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1099 boost::format formatter("out_function: "
1100 "void virtualservice_tcp::edit_virtualservice( "
1101 "const l7vs::virtualservice_element& in,"
1102 "l7vs::error_code& err ): err = %s, err.message = %s");
1103 formatter % (err ? "true" : "false") % err.get_message();
1104 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 63, formatter.str(),
1105 __FILE__, __LINE__);
1109 element.schedule_module_name = elem.schedule_module_name;
1112 //additional PM options(for protomod_url)
1113 protocol_module_base::check_message_result result;
1114 if( NULL != protomod ){
1115 result = protomod->add_parameter( elem.protocol_args );
1117 for( size_t i = 0; i < elem.protocol_args.size(); ++i ){
1118 element.protocol_args.push_back( elem.protocol_args[i] );
1121 err.setter( true, result.message );
1122 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1123 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1124 "const l7vs::virtualservice_element& in,"
1125 "l7vs::error_code& err ): err = %s, err.message = %s");
1126 formatter % ( err ? "true" : "false") % err.get_message();
1127 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 64, formatter.str(),
1128 __FILE__, __LINE__ );
1134 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 14, PROTOMOD_LOAD_ERROR_MSG,
1135 __FILE__, __LINE__ );
1136 err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
1137 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1138 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1139 "const l7vs::virtualservice_element& in,"
1140 "l7vs::error_code& err ): err = %s, err.message = %s");
1141 formatter % ( err ? "true" : "false") % err.get_message();
1142 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 65, formatter.str(),
1143 __FILE__, __LINE__ );
1150 if (ULLONG_MAX == elem.qos_upstream) {
1151 element.qos_upstream = 0ULL;
1152 } else if (0ULL != elem.qos_upstream) {
1153 element.qos_upstream = elem.qos_upstream;
1156 if (ULLONG_MAX == elem.qos_downstream) {
1157 element.qos_downstream = 0ULL;
1158 } else if (0ULL != elem.qos_downstream) {
1159 element.qos_downstream = elem.qos_downstream;
1161 //sorry_maxconnection;
1162 if (LLONG_MAX == elem.sorry_maxconnection) {
1163 element.sorry_maxconnection = 0;
1164 } else if (0 != elem.sorry_maxconnection) {
1165 element.sorry_maxconnection = elem.sorry_maxconnection;
1168 if (INT_MAX == elem.sorry_flag) {
1169 element.sorry_flag = 0;
1170 } else if (0 != elem.sorry_flag) {
1171 element.sorry_flag = 1;
1174 if (virtualservice_element::FWD_NONE != elem.sorry_fwdmode) {
1175 element.sorry_fwdmode = elem.sorry_fwdmode;
1178 //if endpoint of SorryServer equal 255.255.255.255:0,not update
1179 //if equal endpoint 255.255.255.255:0, clear sorry parameters
1180 if (elem.sorry_endpoint ==
1181 boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("255.255.255.255"), (0))) {
1182 element.sorry_endpoint = boost::asio::ip::tcp::endpoint(
1183 boost::asio::ip::address::from_string("0.0.0.0"), (0));
1184 element.sorry_maxconnection = 0LL;
1185 element.sorry_flag = false;
1186 active_sessions.do_all(boost::bind(&session_thread_control::session_sorry_disable, _1));
1188 if (elem.sorry_endpoint != boost::asio::ip::tcp::endpoint(
1189 boost::asio::ip::address::from_string("0.0.0.0"), (0))) {
1190 element.sorry_endpoint = elem.sorry_endpoint;
1192 active_sessions.do_all(boost::bind(
1193 &session_thread_control::session_sorry_mode_change, _1, elem.sorry_flag));
1196 if (elem.access_log_flag != -1) {
1197 // access log flag ON and access log filename not set.
1198 if (elem.access_log_flag == 1 && element.access_log_file_name == "") {
1200 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 15, SCHEDMOD_LOAD_ERROR_MSG,
1201 __FILE__, __LINE__);
1202 err.setter(true, "access log flag change err.");
1206 // access log flag check and send access log output ON or OFF message to tcp_session
1207 element.access_log_flag = elem.access_log_flag;
1208 if (elem.access_log_flag == 1 && access_log_flag == false) {
1209 active_sessions.do_all(boost::bind(
1210 &session_thread_control::session_accesslog_output_mode_on, _1));
1211 access_log_flag = true;
1212 } else if (elem.access_log_flag == 0 && access_log_flag == true) {
1213 active_sessions.do_all(boost::bind(
1214 &session_thread_control::session_accesslog_output_mode_off, _1));
1215 access_log_flag = false;
1219 err.setter(false, "");
1221 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1222 boost::format formatter("out_function: void virtualservice_tcp::set_virtualservice( "
1223 "const l7vs::virtualservice_element& in,"
1224 "l7vs::error_code& err ): err = %s, err.message = %s");
1225 formatter % (err ? "true" : "false") % err.get_message();
1226 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 66, formatter.str(), __FILE__, __LINE__);
1233 * @param virtualservice_element
1237 void l7vs::virtualservice_tcp::add_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1239 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1240 boost::format formatter("in_function: void virtualservice_tcp::add_realserver( "
1241 "const l7vs::virtualservice_element& in,"
1242 "l7vs::error_code& err )");
1243 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 67, formatter.str(), __FILE__, __LINE__);
1246 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1248 //check equal virtualservice
1249 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1250 err.setter(true, "Virtual Service does not exist.");
1251 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1252 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1253 "const l7vs::virtualservice_element& in,"
1254 "l7vs::error_code& err ): err = %s, err.message = %s");
1255 formatter % (err ? "true" : "false") % err.get_message();
1256 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 68, formatter.str(),
1257 __FILE__, __LINE__);
1262 if (in.realserver_vector.size() == 0U) {
1263 err.setter(true, ".");
1264 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1265 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1266 "const l7vs::virtualservice_element& in,"
1267 "l7vs::error_code& err ): err = %s, err.message = %s");
1268 formatter % (err ? "true" : "false") % err.get_message();
1269 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 69, formatter.str(),
1270 __FILE__, __LINE__);
1274 //lock rs_list_ref_count_inc_mutex
1275 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1277 //waiting, rs_list_ref_count become 0
1278 while (rs_list_ref_count != 0ULL) {
1279 boost::this_thread::sleep(
1280 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1284 //check duplication realserver
1285 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1286 itr != in_element.realserver_vector.end();
1288 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1289 rs_itr != rs_list.end(); ++rs_itr) {
1290 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1291 err.setter(true, "Real Server already exist.");
1292 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1293 boost::format formatter("out_function: "
1294 "void virtualservice_tcp::add_realserver( "
1295 "const l7vs::virtualservice_element& in,"
1296 "l7vs::error_code& err ): err = %s, err.message = %s");
1297 formatter % (err ? "true" : "false") % err.get_message();
1298 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 70,
1299 formatter.str(), __FILE__, __LINE__);
1307 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1308 itr != in_element.realserver_vector.end();
1311 rs.tcp_endpoint = itr->tcp_endpoint;
1312 rs.udp_endpoint = itr->udp_endpoint;
1313 rs.weight = itr->weight;
1314 rs.fwdmode = itr->fwdmode;
1315 rs_list.push_back(rs);
1318 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1319 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1320 "const l7vs::virtualservice_element& in,"
1321 "l7vs::error_code& err ): err = %s, err.message = %s");
1322 formatter % (err ? "true" : "false") % err.get_message();
1323 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 71, formatter.str(), __FILE__, __LINE__);
1330 * @param virtualservice_element
1334 void l7vs::virtualservice_tcp::edit_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1336 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1337 boost::format formatter("in_function: void virtualservice_tcp::edit_realserver( "
1338 "const l7vs::virtualservice_element& in,"
1339 "l7vs::error_code& err )");
1340 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 72, formatter.str(), __FILE__, __LINE__);
1342 //check equal virtualservice
1343 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1344 err.setter(true, "Virtual Service does not exist.");
1345 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1346 boost::format formatter("out_function: void virtualservice_tcp::edit_realserver( "
1347 "const l7vs::virtualservice_element& in,"
1348 "l7vs::error_code& err ): err = %s, err.message = %s");
1349 formatter % (err ? "true" : "false") % err.get_message();
1350 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 73, formatter.str(),
1351 __FILE__, __LINE__);
1356 //lock rs_list_ref_count_inc_mutex
1357 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1359 //waiting, rs_list_ref_count become 0
1360 while (rs_list_ref_count != 0ULL) {
1361 boost::this_thread::sleep(
1362 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1366 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1368 //check is exist realserver
1369 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1370 itr != in_element.realserver_vector.end();
1372 bool exist_flag = false;
1373 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1374 rs_itr != rs_list.end(); ++rs_itr) {
1375 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1380 err.setter(true, "Real Server does not exist.");
1381 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1382 boost::format formatter("out_function: "
1383 "void virtualservice_tcp::edit_realserver( "
1384 "const l7vs::virtualservice_element& in,"
1385 "l7vs::error_code& err ): err = %s, err.message = %s");
1386 formatter % (err ? "true" : "false") % err.get_message();
1387 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 74, formatter.str(),
1388 __FILE__, __LINE__);
1394 //lock adm_cmd_wait_flag on
1395 adm_cmd_wait_flag_mutex.lock();
1396 adm_cmd_wait_flag = true;
1397 adm_cmd_wait_flag_cond.notify_one();
1398 adm_cmd_wait_flag_mutex.unlock();
1401 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1402 itr != in_element.realserver_vector.end();
1404 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1405 rs_itr != rs_list.end(); ++rs_itr) {
1406 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1407 rs_itr->udp_endpoint = itr->udp_endpoint;
1409 if (itr->weight != -1) {
1410 rs_itr->weight = itr->weight;
1412 if (itr->fwdmode != realserver_element::FWD_NONE) {
1413 rs_itr->fwdmode = itr->fwdmode;
1419 //lock adm_cmd_wait_flag off
1420 adm_cmd_wait_flag_mutex.lock();
1421 adm_cmd_wait_flag = false;
1422 adm_cmd_wait_flag_cond.notify_one();
1423 adm_cmd_wait_flag_mutex.unlock();
1425 err.setter(false, "");
1426 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1427 boost::format formatter("out_function: void virtualservice_tcp::edit_realserver( "
1428 "const l7vs::virtualservice_element& in,"
1429 "l7vs::error_code& err ): err = %s, err.message = %s");
1430 formatter % (err ? "true" : "false") % err.get_message();
1431 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 75, formatter.str(), __FILE__, __LINE__);
1438 * @param virtualservice_element
1442 void l7vs::virtualservice_tcp::del_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1444 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1445 boost::format formatter("in_function: void virtualservice_tcp::del_realserver( "
1446 "const l7vs::virtualservice_element& in,"
1447 "l7vs::error_code& err )");
1448 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 76, formatter.str(), __FILE__, __LINE__);
1451 //check equal virtualservice
1452 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1453 err.setter(true, "Virtual Service is not equal.");
1454 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1455 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1456 "const l7vs::virtualservice_element& in,"
1457 "l7vs::error_code& err ): err = %s, err.message = %s");
1458 formatter % (err ? "true" : "false") % err.get_message();
1459 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 77, formatter.str(),
1460 __FILE__, __LINE__);
1465 //lock rs_list_ref_count_inc_mutex
1466 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1468 //waiting, rs_list_ref_count become 0
1469 while (rs_list_ref_count != 0ULL) {
1470 boost::this_thread::sleep(
1471 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1475 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1477 //check is exist realserver
1478 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1479 itr != in_element.realserver_vector.end();
1481 bool exist_flag = false;
1482 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1483 rs_itr != rs_list.end(); ++rs_itr) {
1484 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1489 err.setter(true, "Real Server does not exist.");
1490 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1491 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1492 "const l7vs::virtualservice_element& in,"
1493 "l7vs::error_code& err ): err = %s, err.message = %s");
1494 formatter % (err ? "true" : "false") % err.get_message();
1495 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 78, formatter.str(),
1496 __FILE__, __LINE__);
1502 //lock adm_cmd_wait_flag on
1503 adm_cmd_wait_flag_mutex.lock();
1504 adm_cmd_wait_flag = true;
1505 adm_cmd_wait_flag_cond.notify_one();
1506 adm_cmd_wait_flag_mutex.unlock();
1509 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1510 itr != in_element.realserver_vector.end();
1512 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1513 rs_itr != rs_list.end(); ++rs_itr) {
1514 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1515 rs_list.erase(rs_itr);
1516 active_sessions.do_all(boost::bind(&session_thread_control::session_realserver_remove, _1, rs_itr->tcp_endpoint));
1522 //lock adm_cmd_wait_flag off
1523 adm_cmd_wait_flag_mutex.lock();
1524 adm_cmd_wait_flag = false;
1525 adm_cmd_wait_flag_cond.notify_one();
1526 adm_cmd_wait_flag_mutex.unlock();
1528 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1529 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1530 "const l7vs::virtualservice_element& in,"
1531 "l7vs::error_code& err ): err = %s, err.message = %s");
1532 formatter % (err ? "true" : "false") % err.get_message();
1533 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 79, formatter.str(), __FILE__, __LINE__);
1538 * main loop of virtualservice(TCP)
1543 void l7vs::virtualservice_tcp::run()
1545 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function: void virtualservice_tcp::run()",
1546 __FILE__, __LINE__);
1548 if (pool_sessions.size() == 0) {
1549 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.",
1550 __FILE__, __LINE__);
1553 boost::asio::socket_base::receive_buffer_size option(8192 * 192);
1554 acceptor_->set_option(option);
1555 //set socket option TCP_DEFER_ACCEPT
1556 if (defer_accept_opt) {
1557 size_t len = sizeof(defer_accept_val);
1558 int err = ::setsockopt(acceptor_->native(), IPPROTO_TCP, TCP_DEFER_ACCEPT, &defer_accept_val, len);
1559 if (unlikely(err)) {
1561 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
1562 "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__);
1566 acceptor_->listen();
1568 //left session is less than the threshold
1569 if ((sessionpool_alert_flag == false) &&
1570 (pool_sessions.size() < param_data.session_pool_alert_on)) {
1571 //create trap message
1572 trapmessage trap_msg;
1573 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
1574 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
1575 error_code err_code;
1576 //push the trap message
1577 snmpagent::push_trapmessage(trap_msg, err_code);
1579 std::string msg("Push trap message failed.");
1580 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, msg, __FILE__, __LINE__);
1583 //set sessionpool alert flag true
1584 sessionpool_alert_flag = true;
1587 //switch active a session
1588 session_thread_control *stc_ptr;
1590 stc_ptr = pool_sessions.pop();
1593 waiting_session = stc_ptr->get_session().get();
1595 if (!ssl_virtualservice_mode_flag) {
1596 acceptor_->async_accept(waiting_session->get_client_socket().get_socket(),
1597 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1598 boost::asio::placeholders::error));
1600 acceptor_->async_accept(waiting_session->get_client_ssl_socket().lowest_layer(),
1601 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1602 boost::asio::placeholders::error));
1604 //register timer event handler
1605 calc_bps_timer->expires_from_now(boost::posix_time::milliseconds(param_data.bps_interval));
1606 calc_bps_timer->async_wait(boost::bind(&virtualservice_tcp::handle_throughput_update,
1607 this, boost::asio::placeholders::error));
1609 //register handle_replication_interrupt
1610 replication_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1611 replication_timer->async_wait(boost::bind(&virtualservice_tcp::handle_replication_interrupt,
1612 this, boost::asio::placeholders::error));
1613 //register handle_protomod_replication
1614 protomod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1615 protomod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_protomod_replication,
1616 this, boost::asio::placeholders::error));
1617 //register handle_schedmod_replication
1618 schedmod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1619 schedmod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_schedmod_replication,
1620 this, boost::asio::placeholders::error));
1622 //run dispatcher(start io_service loop)
1623 work.reset(new boost::asio::io_service::work(*dispatcher));
1624 boost::thread_group dispatcher_thread_group;
1626 for (int i = 0; i < IO_SERVICE_THREADS_NUM; i++) {
1627 dispatcher_thread_group.create_thread(boost::bind(&boost::asio::io_service::run, dispatcher));
1630 //join dispatcher_thread_group when virtualservice_tcp::stop() executed.
1631 dispatcher_thread_group.join_all();
1633 //stop all active sessions
1635 active_sessions.do_all(boost::bind(&session_thread_control::session_stop, _1));
1645 void l7vs::virtualservice_tcp::stop()
1647 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function: void virtualservice_tcp::stop()",
1648 __FILE__, __LINE__);
1650 boost::system::error_code err;
1651 virtualservice_stop_flag++;
1652 while (interrupt_running_flag.get()) {
1653 boost::this_thread::yield();
1656 acceptor_->close(err);
1658 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__);
1663 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1664 active_sessions.do_all(boost::bind(&session_thread_control::session_stop, _1));
1665 while (active_sessions.size()) {
1666 boost::this_thread::yield();
1670 calc_bps_timer->cancel();
1671 replication_timer->cancel();
1672 protomod_rep_timer->cancel();
1673 schedmod_rep_timer->cancel();
1676 dispatcher->reset();
1682 * increment active-connection count
1687 void l7vs::virtualservice_tcp::connection_active(const boost::asio::ip::tcp::endpoint &in)
1689 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1690 boost::format formatter("in_function: void virtualservice_tcp::connection_active( "
1691 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1693 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__);
1696 for (std::list<realserver>::iterator itr = rs_list.begin();
1697 itr != rs_list.end();
1699 if (itr->tcp_endpoint == in) {
1700 itr->increment_active();
1707 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1708 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 83, "out_function: "
1709 "void virtualservice_tcp::connection_active()", __FILE__, __LINE__);
1714 * increment in-active-connection (and decrement active-connection count)
1719 void l7vs::virtualservice_tcp::connection_inactive(const boost::asio::ip::tcp::endpoint &in)
1721 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1722 boost::format formatter("in_function: void virtualservice_tcp::connection_inactive( "
1723 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1725 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__);
1728 for (std::list<realserver>::iterator itr = rs_list.begin();
1729 itr != rs_list.end();
1731 if (itr->tcp_endpoint == in) {
1732 itr->decrement_active();
1733 itr->increment_inact();
1740 //left session is more than the release threshold
1741 if ((sessionpool_alert_flag == true) &&
1742 ((pool_sessions.size() + 1) > param_data.session_pool_alert_off)) {
1743 //create trap message
1744 trapmessage trap_msg;
1745 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_OFF;
1746 trap_msg.message = "TRAP00020012,Warning release: The left-session has exceeded the release threshold of left-session warning.";
1747 error_code err_code;
1748 //push the trap message
1749 snmpagent::push_trapmessage(trap_msg, err_code);
1751 std::string msg("Push trap message failed.");
1752 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 39, msg, __FILE__, __LINE__);
1755 //set sessionpool alert flag true
1756 sessionpool_alert_flag = false;
1759 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1760 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 85, "out_function: "
1761 "void virtualservice_tcp::connection_inactive()", __FILE__, __LINE__);
1771 void l7vs::virtualservice_tcp::release_session(const tcp_session *session_ptr)
1773 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1774 boost::format funclog_fmt("in_function: void virtualservice_tcp::release_session( "
1775 "const tcp_session* session_ptr ): session_ptr = %d");
1776 funclog_fmt % session_ptr;
1777 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 86, funclog_fmt.str(), __FILE__, __LINE__);
1780 session_thread_control *stc_ptr = active_sessions.find(session_ptr);
1781 if (unlikely(NULL == stc_ptr)) {
1782 boost::format fmt("session release fail: "
1783 "active_sessions.find( const tcp_session* session_ptr = %d )");
1785 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*XXX*/999, fmt.str(), __FILE__, __LINE__);
1786 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1787 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 88, "out_function: "
1788 "void virtualservice_tcp::release_session( "
1789 "const boost::thread::id thread_id )", __FILE__, __LINE__);
1794 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1795 boost::format fmt1("pool_session.size = %d");
1796 fmt1 % pool_sessions.size();
1797 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 89, fmt1.str(), __FILE__, __LINE__);
1798 boost::format fmt2("active_session.size = %d");
1799 fmt2 % active_sessions.size();
1800 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 90, fmt2.str(), __FILE__, __LINE__);
1801 boost::format fmt3("active_count = %d");
1802 fmt3 % active_count.get();
1803 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 91, fmt3.str(), __FILE__, __LINE__);
1805 active_sessions.erase(session_ptr);
1807 while (!pool_sessions.push(stc_ptr)) {}
1809 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1810 boost::format fmt1("pool_session.size = %d");
1811 fmt1 % pool_sessions.size();
1812 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 92, fmt1.str(), __FILE__, __LINE__);
1813 boost::format fmt2("active_session.size = %d");
1814 fmt2 % active_sessions.size();
1815 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 93, fmt2.str(), __FILE__, __LINE__);
1816 boost::format fmt3("active_count = %d");
1817 fmt3 % active_count.get();
1818 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 94, fmt3.str(), __FILE__, __LINE__);
1820 boost::format funclog_fmt("out_function: void virtualservice_tcp::release_session( "
1821 "const tcp_session* session_ptr ): session_ptr = %d");
1822 funclog_fmt % session_ptr;
1823 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 95, funclog_fmt.str(), __FILE__, __LINE__);
1828 // set_socket_option
1830 void l7vs::virtualservice_tcp::set_socket_option()
1833 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1834 boost::format funclog_fmt("in_function: void virtualservice_tcp::et_socket_option");
1835 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 96, funclog_fmt.str(), __FILE__, __LINE__);
1838 // socket option check & set
1839 //! TCP_DEFER_ACCEPT (false:not set,true:set option)
1840 defer_accept_opt = false;
1841 //! TCP_DEFER_ACCEPT option value
1842 defer_accept_val = 0;
1843 //! TCP_NODELAY (false:not set,true:set option)
1844 set_sock_opt.nodelay_opt = false;
1845 //! TCP_NODELAY option value (false:off,true:on)
1846 set_sock_opt.nodelay_val = false;
1847 //! TCP_CORK (false:not set,true:set option)
1848 set_sock_opt.cork_opt = false;
1849 //! TCP_CORK option value (false:off,true:on)
1850 set_sock_opt.cork_val = false;
1851 //! TCP_QUICKACK (false:not set,true:set option)
1852 set_sock_opt.quickack_opt = false;
1853 //! TCP_QUICKACK option value (false:off,true:on)
1854 set_sock_opt.quickack_val = false;
1856 // set socket option
1857 if (element.socket_option_tcp_defer_accept != 0) {
1858 defer_accept_opt = true;
1859 if (element.socket_option_tcp_defer_accept == 1) {
1860 defer_accept_val = 1;
1864 if (element.socket_option_tcp_nodelay != 0) {
1865 set_sock_opt.nodelay_opt = true;
1866 if (element.socket_option_tcp_nodelay == 1) {
1867 set_sock_opt.nodelay_val = true;
1871 if (element.socket_option_tcp_cork != 0) {
1872 set_sock_opt.cork_opt = true;
1873 if (element.socket_option_tcp_cork == 1) {
1874 set_sock_opt.cork_val = true;
1878 if (element.socket_option_tcp_quickack != 0) {
1879 set_sock_opt.quickack_opt = true;
1880 if (element.socket_option_tcp_quickack == 1) {
1881 set_sock_opt.quickack_val = true;
1885 //----Debug log----------------------------------------------------------------------
1886 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1887 boost::format formatter("set_socket_option"
1888 " defer_accept_opt[%s]"
1889 " defer_accept_val[%d]"
1895 " quickack_val[%s]");
1897 % (defer_accept_opt ? "true" : "false")
1899 % (set_sock_opt.nodelay_opt ? "true" : "false")
1900 % (set_sock_opt.nodelay_val ? "true" : "false")
1901 % (set_sock_opt.cork_opt ? "true" : "false")
1902 % (set_sock_opt.cork_val ? "true" : "false")
1903 % (set_sock_opt.quickack_opt ? "true" : "false")
1904 % (set_sock_opt.quickack_val ? "true" : "false");
1905 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 97, formatter.str(), __FILE__, __LINE__);
1907 //----Debug log----------------------------------------------------------------------
1911 //! get private key file password (for callback function)
1912 //! @return password string
1913 std::string l7vs::virtualservice_tcp::get_ssl_password()
1915 //*-------- DEBUG LOG --------*/
1916 if (unlikely(LOG_LV_DEBUG ==
1917 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1918 std::stringstream buf;
1919 buf << "in_function: ";
1920 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password()";
1921 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 98, buf.str(),
1922 __FILE__, __LINE__);
1924 //*------ DEBUG LOG END ------*/
1926 // Get password from file.
1927 std::string retstr = "";
1929 char buf[MAX_SSL_PASSWD_SIZE + 3];
1930 if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1932 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1933 "Password file cannot open.", __FILE__, __LINE__);
1935 if (fgets(buf, MAX_SSL_PASSWD_SIZE + 3, fp) == NULL) {
1936 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
1937 "Password not found in file.",
1938 __FILE__, __LINE__);
1940 if (strlen(buf) > MAX_SSL_PASSWD_SIZE) {
1941 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1942 "Password is too long.",
1943 __FILE__, __LINE__);
1945 buf[strlen(buf) - 1] = '\0';
1952 //*-------- DEBUG LOG --------*/
1953 if (unlikely(LOG_LV_DEBUG ==
1954 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1955 std::stringstream buf;
1956 buf << "out_function: ";
1957 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password(): ";
1958 buf << "retstr = " << retstr;
1959 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 99, buf.str(),
1960 __FILE__, __LINE__);
1962 //*------ DEBUG LOG END ------*/
1968 //! Convert verify option string to integer(#define).
1970 //! @param[in] opt_string option string
1971 //! @retval ret option value
1972 //! @retval -1 no match
1973 int l7vs::virtualservice_tcp::conv_verify_option(std::string opt_string)
1975 //*-------- DEBUG LOG --------*/
1976 if (unlikely(LOG_LV_DEBUG ==
1977 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1978 std::stringstream buf;
1979 buf << "in_function: ";
1980 buf << "int virtualservice_tcp::conv_verify_option";
1981 buf << "(std::string opt_string): ";
1982 buf << "opt_string = " << opt_string;
1983 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 100, buf.str(),
1984 __FILE__, __LINE__);
1986 //*------ DEBUG LOG END ------*/
1990 // /usr/include/openssl/ssl.h
1991 // #define SSL_VERIFY_NONE 0x00
1992 // #define SSL_VERIFY_PEER 0x01
1993 // #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
1994 // #define SSL_VERIFY_CLIENT_ONCE 0x04
1996 if (opt_string == "SSL_VERIFY_NONE") {
1997 ret = SSL_VERIFY_NONE;
1998 } else if (opt_string == "SSL_VERIFY_PEER") {
1999 ret = SSL_VERIFY_PEER;
2000 } else if (opt_string == "SSL_VERIFY_FAIL_IF_NO_PEER_CERT") {
2001 ret = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2002 } else if (opt_string == "SSL_VERIFY_CLIENT_ONCE") {
2003 ret = SSL_VERIFY_CLIENT_ONCE;
2005 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2006 "verify option string no match.",
2007 __FILE__, __LINE__);
2010 //*-------- DEBUG LOG --------*/
2011 if (unlikely(LOG_LV_DEBUG ==
2012 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2013 std::stringstream buf;
2014 buf << "out_function: ";
2015 buf << "int virtualservice_tcp::conv_verify_option";
2016 buf << "(std::string opt_string): ";
2017 buf << "return_value = " << ret;
2018 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 101, buf.str(),
2019 __FILE__, __LINE__);
2021 //*------ DEBUG LOG END ------*/
2022 // if ret == -1 then No match.
2027 // Convert SSL option string to integer(#define).
2029 // @param[in] opt_string option string
2030 // @retval ret option value
2031 // @retval -1 no match
2032 long int l7vs::virtualservice_tcp::conv_ssl_option(std::string opt_string)
2034 //*-------- DEBUG LOG --------*/
2035 if (unlikely(LOG_LV_DEBUG ==
2036 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2037 std::stringstream buf;
2038 buf << "in_function: ";
2039 buf << "long int virtualservice_tcp::conv_ssl_option";
2040 buf << "(std::string opt_string): ";
2041 buf << "opt_string = " << opt_string;
2042 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 102, buf.str(),
2043 __FILE__, __LINE__);
2045 //*------ DEBUG LOG END ------*/
2049 // /usr/include/openssl/ssl.h
2050 // #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
2051 // #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
2052 // #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
2053 // #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
2054 // #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
2055 // #define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L
2056 // #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
2057 // #define SSL_OP_TLS_D5_BUG 0x00000100L
2058 // #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
2059 // #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L
2060 // #define SSL_OP_ALL 0x00000FF7L
2061 // #define SSL_OP_NO_QUERY_MTU 0x00001000L
2062 // #define SSL_OP_COOKIE_EXCHANGE 0x00002000L
2063 // #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
2064 // #define SSL_OP_SINGLE_ECDH_USE 0x00080000L
2065 // #define SSL_OP_SINGLE_DH_USE 0x00100000L
2066 // #define SSL_OP_EPHEMERAL_RSA 0x00200000L
2067 // #define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
2068 // #define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
2069 // #define SSL_OP_NO_SSLv2 0x01000000L
2070 // #define SSL_OP_NO_SSLv3 0x02000000L
2071 // #define SSL_OP_NO_TLSv1 0x04000000L
2072 // #define SSL_OP_PKCS1_CHECK_1 0x08000000L
2073 // #define SSL_OP_PKCS1_CHECK_2 0x10000000L
2074 // #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
2075 // #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
2076 if (opt_string == "SSL_OP_MICROSOFT_SESS_ID_BUG") {
2077 ret = SSL_OP_MICROSOFT_SESS_ID_BUG;
2078 } else if (opt_string == "SSL_OP_NETSCAPE_CHALLENGE_BUG") {
2079 ret = SSL_OP_NETSCAPE_CHALLENGE_BUG;
2080 } else if (opt_string == "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG") {
2081 ret = SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
2082 } else if (opt_string == "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG") {
2083 ret = SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
2084 } else if (opt_string == "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER") {
2085 ret = SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
2086 } else if (opt_string == "SSL_OP_MSIE_SSLV2_RSA_PADDING") {
2087 ret = SSL_OP_MSIE_SSLV2_RSA_PADDING;
2088 } else if (opt_string == "SSL_OP_SSLEAY_080_CLIENT_DH_BUG") {
2089 ret = SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
2090 } else if (opt_string == "SSL_OP_TLS_D5_BUG") {
2091 ret = SSL_OP_TLS_D5_BUG;
2092 } else if (opt_string == "SSL_OP_TLS_BLOCK_PADDING_BUG") {
2093 ret = SSL_OP_TLS_BLOCK_PADDING_BUG;
2094 } else if (opt_string == "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS") {
2095 ret = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
2096 } else if (opt_string == "SSL_OP_ALL") {
2097 // boost::asio::ssl::context::default_workarounds
2099 } else if (opt_string == "SSL_OP_NO_QUERY_MTU") {
2100 ret = SSL_OP_NO_QUERY_MTU;
2101 } else if (opt_string == "SSL_OP_COOKIE_EXCHANGE") {
2102 ret = SSL_OP_COOKIE_EXCHANGE;
2103 } else if (opt_string == "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION") {
2104 ret = SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
2105 } else if (opt_string == "SSL_OP_SINGLE_ECDH_USE") {
2106 ret = SSL_OP_SINGLE_ECDH_USE;
2107 } else if (opt_string == "SSL_OP_SINGLE_DH_USE") {
2108 // boost::asio::ssl::context::single_dh_use
2109 ret = SSL_OP_SINGLE_DH_USE;
2110 } else if (opt_string == "SSL_OP_EPHEMERAL_RSA") {
2111 ret = SSL_OP_EPHEMERAL_RSA;
2112 } else if (opt_string == "SSL_OP_CIPHER_SERVER_PREFERENCE") {
2113 ret = SSL_OP_CIPHER_SERVER_PREFERENCE;
2114 } else if (opt_string == "SSL_OP_TLS_ROLLBACK_BUG") {
2115 ret = SSL_OP_TLS_ROLLBACK_BUG;
2116 } else if (opt_string == "SSL_OP_NO_SSLv2") {
2117 // boost::asio::ssl::context::no_sslv2
2118 ret = SSL_OP_NO_SSLv2;
2119 } else if (opt_string == "SSL_OP_NO_SSLv3") {
2120 // boost::asio::ssl::context::no_sslv3
2121 ret = SSL_OP_NO_SSLv3;
2122 } else if (opt_string == "SSL_OP_NO_TLSv1") {
2123 // boost::asio::ssl::context::no_tlsv1
2124 ret = SSL_OP_NO_TLSv1;
2125 } else if (opt_string == "SSL_OP_PKCS1_CHECK_1") {
2126 ret = SSL_OP_PKCS1_CHECK_1;
2127 } else if (opt_string == "SSL_OP_PKCS1_CHECK_2") {
2128 ret = SSL_OP_PKCS1_CHECK_2;
2129 } else if (opt_string == "SSL_OP_NETSCAPE_CA_DN_BUG") {
2130 ret = SSL_OP_NETSCAPE_CA_DN_BUG;
2131 } else if (opt_string == "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG") {
2132 ret = SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
2134 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
2135 "ssl option string no match.",
2136 __FILE__, __LINE__);
2139 //*-------- DEBUG LOG --------*/
2140 if (unlikely(LOG_LV_DEBUG ==
2141 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2142 std::stringstream buf;
2143 buf << "out_function: ";
2144 buf << "long int virtualservice_tcp::conv_ssl_option";
2145 buf << "(std::string opt_string): ";
2146 buf << "return_value = " << ret;
2147 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 103, buf.str(),
2148 __FILE__, __LINE__);
2150 //------ DEBUG LOG END ------*/
2151 // if ret == -1 then No match.
2156 //! get ssl parameter
2157 //! @return get ssl parameter result
2158 bool l7vs::virtualservice_tcp::get_ssl_parameter()
2160 //*-------- DEBUG LOG --------*/
2161 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2162 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 104,
2163 "in_function: bool virtualservice_tcp::get_ssl_parameter()",
2164 __FILE__, __LINE__);
2166 //*------ DEBUG LOG END ------*/
2167 typedef std::vector< std::string > string_vector_type;
2170 string_vector_type string_vector;
2171 l7vs::error_code err;
2172 bool retbool = false;
2175 // param init ( ssl configuration file )
2176 if (unlikely(!param.init(l7vs::PARAM_COMP_SSL, ssl_file_name))) {
2177 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 24,
2178 "SSL config file read error.",
2179 __FILE__, __LINE__);
2183 //// SSL context parameter
2184 // Get parameter "ca_dir".
2185 ca_dir = param.get_string(l7vs::PARAM_COMP_SSL, "ca_dir",
2186 err, ssl_file_name);
2187 if (unlikely(err) || ca_dir == "") {
2188 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 9,
2189 "ca_dir parameter not found. Use default value.",
2190 __FILE__, __LINE__);
2191 ca_dir = DEFAULT_SSL_CA_DIR;
2194 // Get parameter "ca_file".
2195 ca_file = param.get_string(l7vs::PARAM_COMP_SSL, "ca_file",
2196 err, ssl_file_name);
2197 if (unlikely(err)) {
2198 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 25,
2199 "Cannot get ca_file parameter.",
2200 __FILE__, __LINE__);
2204 // Get parameter "cert_chain_dir".
2205 cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2209 if (unlikely(err) || cert_chain_dir == "") {
2210 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 10,
2211 "cert_chain_dir parameter not found. Use default value.",
2212 __FILE__, __LINE__);
2213 cert_chain_dir = DEFAULT_SSL_CERT_CHAIN_DIR;
2216 // Get parameter "cert_chain_file".
2217 cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
2221 if (unlikely(err) || cert_chain_file == "") {
2222 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 26,
2223 "Cannot get cert_chain_file parameter.",
2224 __FILE__, __LINE__);
2228 // Get parameter "private_key_dir".
2229 private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2233 if (unlikely(err) || private_key_dir == "") {
2234 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 11,
2235 "private_key_dir parameter not found. Use default value.",
2236 __FILE__, __LINE__);
2237 private_key_dir = DEFAULT_SSL_PRIVATE_KEY_DIR;
2240 // Get parameter "private_key_file".
2241 private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
2245 if (unlikely(err) || private_key_file == "") {
2246 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 27,
2247 "Cannot get private_key_file parameter.",
2248 __FILE__, __LINE__);
2252 // Get parameter "private_key_filetype".
2253 // and convert string to filetype define value.
2255 // /usr/include/openssl/ssl.h
2256 // #define SSL_FILETYPE_PEM X509_FILETYPE_PEM ->1
2257 // #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 ->2
2258 std::string filetype_str = param.get_string(
2259 l7vs::PARAM_COMP_SSL,
2260 "private_key_filetype",
2263 if (unlikely(err) || filetype_str == "") {
2264 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 12,
2265 "private_key_filetype parameter not found. Use default value.",
2266 __FILE__, __LINE__);
2267 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
2268 } else if (filetype_str == "SSL_FILETYPE_PEM") {
2269 private_key_filetype = boost::asio::ssl::context::pem;
2270 } else if (filetype_str == "SSL_FILETYPE_ASN1") {
2271 private_key_filetype = boost::asio::ssl::context::asn1;
2273 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
2274 "private_key_filetype convert error.",
2275 __FILE__, __LINE__);
2279 // Get parameter "private_key_passwd_dir".
2280 private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2281 "private_key_passwd_dir",
2284 if (unlikely(err) || private_key_passwd_dir == "") {
2285 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 13,
2286 "private_key_passwd_dir parameter not found. Use default value.",
2287 __FILE__, __LINE__);
2288 private_key_passwd_dir = DEFAULT_SSL_PRIVATE_KEY_PASSWD_DIR;
2291 // Get parameter "private_key_passwd_file".
2292 private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2293 "private_key_passwd_file",
2296 if (unlikely(err) || private_key_passwd_file == "") {
2297 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
2298 "Cannot get private_key_passwd_file parameter.",
2299 __FILE__, __LINE__);
2303 // Get parameter "verify_options".
2304 param.get_multistring(l7vs::PARAM_COMP_SSL,
2309 if (unlikely(err)) {
2310 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 14,
2311 "verify_options parameter not found. Use default value.",
2312 __FILE__, __LINE__);
2313 verify_options = DEFAULT_SSL_VERIFY_OPTIONS;
2315 // Make verify option bit data.
2316 for (string_vector_type::iterator itr = string_vector.begin();
2317 itr != string_vector.end(); ++itr) {
2318 // Convert string to define value.
2319 int int_val = conv_verify_option(*itr);
2320 if (unlikely(int_val == -1)) {
2321 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 30,
2322 "verify_options convert error.",
2323 __FILE__, __LINE__);
2326 verify_options = (verify_options | int_val);
2330 // Get parameter "verify_cert_depth".
2331 verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2332 "verify_cert_depth",
2335 if (unlikely(err)) {
2336 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 15,
2337 "verify_cert_depth parameter not found. Use default value.",
2338 __FILE__, __LINE__);
2339 verify_cert_depth = DEFAULT_SSL_VERIFY_CERT_DEPTH;
2340 } else if (unlikely(verify_cert_depth < 0 ||
2341 verify_cert_depth > INT_MAX)) {
2342 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 31,
2343 "Invalid verify_cert_depth parameter value.",
2344 __FILE__, __LINE__);
2348 // Get parameter "ssl_options".
2349 // and Check dh parameter file use or not.
2350 is_tmp_dh_use = false;
2351 param.get_multistring(l7vs::PARAM_COMP_SSL,
2356 if (unlikely(err)) {
2357 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 16,
2358 "ssl_options parameter not found. Use default value.",
2359 __FILE__, __LINE__);
2360 ssl_options = DEFAULT_SSL_OPTIONS;
2361 is_tmp_dh_use = true;
2363 // Make ssl option bit data.
2364 for (string_vector_type::iterator itr = string_vector.begin();
2365 itr != string_vector.end(); ++itr) {
2366 // Convert string to define value.
2367 long int longint_val = conv_ssl_option(*itr);
2368 if (unlikely(longint_val == -1)) {
2369 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 32,
2370 "ssl_options convert error.",
2371 __FILE__, __LINE__);
2373 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2374 is_tmp_dh_use = true;
2376 ssl_options = (ssl_options | longint_val);
2380 if (is_tmp_dh_use) {
2381 // Get parameter "tmp_dh_dir".
2382 tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2386 if (unlikely(err) || tmp_dh_dir == "") {
2387 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
2388 "tmp_dh_dir parameter not found. Use default value.",
2389 __FILE__, __LINE__);
2390 tmp_dh_dir = DEFAULT_SSL_TMP_DH_DIR;
2392 // Get parameter "tmp_dh_file".
2393 tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2397 if (unlikely(err) || tmp_dh_file == "") {
2398 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 33,
2399 "Cannot get tmp_dh_file parameter.",
2400 __FILE__, __LINE__);
2405 // Get parameter "cipher_list".
2406 cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2410 if (unlikely(err) || cipher_list == "") {
2411 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 18,
2412 "cipher_list parameter not found. Use default value.",
2413 __FILE__, __LINE__);
2414 cipher_list = DEFAULT_SSL_CIPHER_LIST;
2417 //// SSL session cache parameter
2418 // Get parameter "session_cache".
2419 is_session_cache_use = false;
2420 std::string cache_str = param.get_string(l7vs::PARAM_COMP_SSL,
2424 if (unlikely(err) || cache_str == "") {
2425 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
2426 "session_cache parameter not found. Use default value.",
2427 __FILE__, __LINE__);
2428 is_session_cache_use = true;
2429 } else if (cache_str == "on") {
2430 is_session_cache_use = true;
2431 } else if (cache_str == "off") {
2432 is_session_cache_use = false;
2434 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2435 "Invalid session_cache parameter value.", __FILE__, __LINE__);
2439 if (is_session_cache_use) {
2440 session_cache_mode = DEFAULT_SSL_SESSION_CACHE_MODE;
2441 // Get parameter "session_cache_size".
2442 session_cache_size = param.get_int(l7vs::PARAM_COMP_SSL,
2443 "session_cache_size",
2446 if (unlikely(err)) {
2447 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
2448 "session_cache_size parameter not found. Use default value.",
2449 __FILE__, __LINE__);
2450 session_cache_size = DEFAULT_SSL_SESSION_CACHE_SIZE;
2451 } else if (session_cache_size < 0 ||
2452 session_cache_size > INT_MAX) {
2453 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 35,
2454 "Invalid session_cache_size parameter value.", __FILE__, __LINE__);
2457 // Get parameter "session_cache_timeout".
2458 session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2459 "session_cache_timeout",
2462 if (unlikely(err)) {
2463 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
2464 "session_cache_timeout parameter not found. Use default value.",
2465 __FILE__, __LINE__);
2466 session_cache_timeout = DEFAULT_SSL_SESSION_CACHE_TIMEOUT;
2467 } else if (session_cache_timeout < 0 ||
2468 session_cache_timeout > INT_MAX) {
2469 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 36,
2470 "Invalid session_cache_timeout parameter value.",
2471 __FILE__, __LINE__);
2475 session_cache_mode = SSL_SESS_CACHE_OFF;
2478 //// SSL handshake timer parameter
2479 // Get parameter "timeout_sec".
2480 handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2484 if (unlikely(err)) {
2485 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2486 "timeout_sec parameter not found. Use default value.", __FILE__, __LINE__);
2487 handshake_timeout = DEFAULT_SSL_HANDSHAKE_TIMEOUT;
2488 } else if (handshake_timeout <= 0 || handshake_timeout > INT_MAX) {
2489 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 37,
2490 "Invalid timeout_sec parameter value.", __FILE__, __LINE__);
2500 //*-------- DEBUG LOG --------*/
2501 if (unlikely(LOG_LV_DEBUG ==
2502 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2503 std::stringstream buf;
2504 buf << "out_function: bool virtualservice_tcp::get_ssl_parameter(): ";
2505 buf << "ca_dir = " << ca_dir << ", ";
2506 buf << "ca_file = " << ca_file << ", ";
2507 buf << "cert_chain_dir = " << cert_chain_dir << ", ";
2508 buf << "cert_chain_file = " << cert_chain_file << ", ";
2509 buf << "private_key_dir = " << private_key_dir << ", ";
2510 buf << "private_key_file = " << private_key_file << ", ";
2511 buf << "private_key_filetype = " << private_key_filetype << ", ";
2512 buf << "private_key_passwd_dir = " << private_key_passwd_dir << ", ";
2513 buf << "private_key_passwd_file = " << private_key_passwd_file << ", ";
2514 buf << "verify_options = " << verify_options << ", ";
2515 buf << "verify_cert_depth = " << verify_cert_depth << ", ";
2516 buf << "ssl_options = " << ssl_options << ", ";
2517 if (is_tmp_dh_use) {
2518 buf << "tmp_dh_dir = " << tmp_dh_dir << ", ";
2519 buf << "tmp_dh_file = " << tmp_dh_file << ", ";
2521 buf << "cipher_list = " << cipher_list << ", ";
2522 buf << "session_cache_mode = " << session_cache_mode << ", ";
2523 if (is_session_cache_use) {
2524 buf << "session_cache_size = " << session_cache_size << ", ";
2525 buf << "session_cache_timeout = " << session_cache_timeout << ", ";
2527 buf << "handshake_timeout = " << handshake_timeout;
2528 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2530 __FILE__, __LINE__);
2532 //*------ DEBUG LOG END ------*/
2537 // set ssl context and ssl session cache configuration
2538 // @return set ssl config result
2539 bool l7vs::virtualservice_tcp::set_ssl_config()
2541 //*-------- DEBUG LOG --------*/
2542 if (unlikely(LOG_LV_DEBUG ==
2543 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2544 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 106,
2545 "in_function: bool virtualservice_tcp::set_ssl_config()",
2546 __FILE__, __LINE__);
2548 //*------ DEBUG LOG END ------*/
2550 bool retbool = false;
2553 //// SSL context setting.
2555 if (ca_file.size() == 0) {
2556 // specified CA path.
2558 sslcontext->add_verify_path(ca_dir);
2559 } catch (std::exception &e) {
2560 std::stringstream buf;
2561 buf << "Set root CA path error: " << e.what() << ".";
2562 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2564 __FILE__, __LINE__);
2568 // specified CA file.
2570 sslcontext->load_verify_file(ca_dir + ca_file);
2571 } catch (std::exception &e) {
2572 std::stringstream buf;
2573 buf << "Set root CA file error: " << e.what() << ".";
2574 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2576 __FILE__, __LINE__);
2581 // Set certificate chain file.
2583 sslcontext->use_certificate_chain_file(
2584 cert_chain_dir + cert_chain_file);
2585 } catch (std::exception &e) {
2586 std::stringstream buf;
2587 buf << "Set certificate chain file error: " << e.what() << ".";
2588 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2589 __FILE__, __LINE__);
2593 // Set password callback function.
2595 sslcontext->set_password_callback(
2596 boost::bind(&virtualservice_tcp::get_ssl_password, this));
2597 } catch (std::exception &e) {
2598 std::stringstream buf;
2599 buf << "Set password callback error: " << e.what() << ".";
2600 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2601 __FILE__, __LINE__);
2605 // Set private key file and filetype.
2607 sslcontext->use_private_key_file(
2608 private_key_dir + private_key_file, private_key_filetype);
2609 } catch (std::exception &e) {
2610 std::stringstream buf;
2611 buf << "Set private key file and filetype error: " << e.what() << ".";
2612 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2613 __FILE__, __LINE__);
2617 // Set verify options on the context.
2619 sslcontext->set_verify_mode(verify_options);
2620 } catch (std::exception &e) {
2621 std::stringstream buf;
2622 buf << "Set verify option error: " << e.what() << ".";
2623 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2624 __FILE__, __LINE__);
2628 // Set verify depth on the context.
2629 SSL_CTX_set_verify_depth(sslcontext->impl(), verify_cert_depth);
2631 // Set SSL options on the context.
2633 sslcontext->set_options(ssl_options);
2634 } catch (std::exception &e) {
2635 std::stringstream buf;
2636 buf << "Set SSL option error: " << e.what() << ".";
2637 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2638 __FILE__, __LINE__);
2642 // Set temporary Diffie-Hellman parameters file.
2643 if (is_tmp_dh_use) {
2645 sslcontext->use_tmp_dh_file(tmp_dh_dir + tmp_dh_file);
2646 } catch (std::exception &e) {
2647 std::stringstream buf;
2648 buf << "Set tmp DH file error: " << e.what() << ".";
2649 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2651 __FILE__, __LINE__);
2657 // Set cipher list on the context.
2658 if (unlikely(SSL_CTX_set_cipher_list(sslcontext->impl(),
2659 cipher_list.c_str()) != 1)) {
2660 std::stringstream buf;
2661 buf << "Set cipher list error.";
2662 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2664 __FILE__, __LINE__);
2668 //// SSL session cache setting.
2669 if (is_session_cache_use) {
2670 // Set session id context on the context.
2671 if (unlikely(SSL_CTX_set_session_id_context(
2673 (const unsigned char *)"ultramonkey", 11) != 1)) {
2674 std::stringstream buf;
2675 buf << "Set session id context error.";
2676 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2678 __FILE__, __LINE__);
2682 // Set session cache mode on the context.
2683 SSL_CTX_set_session_cache_mode(
2684 sslcontext->impl(), session_cache_mode);
2686 // Set session cache size on the context.
2687 SSL_CTX_sess_set_cache_size(sslcontext->impl(), session_cache_size);
2689 // Set session cache timeout on the context.
2690 SSL_CTX_set_timeout(sslcontext->impl(), session_cache_timeout);
2693 // session cache OFF.
2694 SSL_CTX_set_session_cache_mode(sslcontext->impl(),
2695 SSL_SESS_CACHE_OFF);
2703 //*-------- DEBUG LOG --------*/
2704 if (unlikely(LOG_LV_DEBUG ==
2705 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2706 std::stringstream buf;
2707 buf << "out_function: bool virtualservice_tcp::set_ssl_config(): ";
2708 get_ssl_config(buf);
2709 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 117, buf.str(),
2710 __FILE__, __LINE__);
2712 //*------ DEBUG LOG END ------*/
2717 // flush ssl session
2718 void l7vs::virtualservice_tcp::flush_ssl_session()
2720 // check expired cached sessions and do flushing
2721 // Need ssl_context lock?
2722 SSL_CTX_flush_sessions(sslcontext->impl(), time(0));
2726 // get ssl configuration form ssl context. (for debug)
2727 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream &buf)
2729 buf << "SSL configuration information: ";
2730 buf << "Verify mode[" << SSL_CTX_get_verify_mode(sslcontext->impl()) << "] ";
2731 buf << "Verify depth[" << SSL_CTX_get_verify_depth(sslcontext->impl()) << "] ";
2732 buf << "SSL options[" << SSL_CTX_get_options(sslcontext->impl()) << "] ";
2733 buf << "Cache mode[" << SSL_CTX_get_session_cache_mode(sslcontext->impl()) << "] ";
2734 buf << "Cache size[" << SSL_CTX_sess_get_cache_size(sslcontext->impl()) << "] ";
2735 buf << "Cache timeout[" << SSL_CTX_get_timeout(sslcontext->impl()) << "] ";
2739 // get ssl session cache information form ssl context. (for debug)
2740 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream &buf)
2742 buf << "SSL session cache information: ";
2743 buf << "Session number[" << SSL_CTX_sess_number(sslcontext->impl()) << "] ";
2744 buf << "Accept[" << SSL_CTX_sess_accept(sslcontext->impl()) << "] ";
2745 buf << "Accept good[" << SSL_CTX_sess_accept_good(sslcontext->impl()) << "] ";
2746 buf << "Accept renegotiate[" << SSL_CTX_sess_accept_renegotiate(sslcontext->impl()) << "] ";
2747 buf << "Hits[" << SSL_CTX_sess_hits(sslcontext->impl()) << "] ";
2748 buf << "Misses[" << SSL_CTX_sess_misses(sslcontext->impl()) << "] ";
2749 buf << "Timeouts[" << SSL_CTX_sess_timeouts(sslcontext->impl()) << "] ";
2750 buf << "Cache full[" << SSL_CTX_sess_cache_full(sslcontext->impl()) << "] ";