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){
51 access_log_file_name = "";
52 dispatcher.reset( new boost::asio::io_service( 10 ) );
53 calc_bps_timer.reset(new boost::asio::deadline_timer(*dispatcher));
54 replication_timer.reset(new boost::asio::deadline_timer(*dispatcher));
55 protomod_rep_timer.reset(new boost::asio::deadline_timer(*dispatcher));
56 schedmod_rep_timer.reset(new boost::asio::deadline_timer(*dispatcher));
57 acceptor_.reset( new boost::asio::ip::tcp::acceptor( *dispatcher ) );
58 sslcontext.reset( new boost::asio::ssl::context( *dispatcher, DEFAULT_SSL_METHOD ) );
65 private_key_file = "";
66 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
67 private_key_passwd_dir = "";
68 private_key_passwd_file = "";
70 verify_cert_depth = 0;
72 is_tmp_dh_use = false;
76 is_session_cache_use = false;
77 session_cache_mode = 0;
78 session_cache_size = 0;
79 session_cache_timeout = 0;
80 handshake_timeout = 0;
83 * virtualservice_tcp class destructor.
85 l7vs::virtualservice_tcp::~virtualservice_tcp()
89 * replication interrupt event
94 void l7vs::virtualservice_tcp::handle_replication_interrupt(const boost::system::error_code &err)
96 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
97 boost::format fmt("in_function: void virtualservice_tcp::handle_replication_interrupt( "
98 "const boost::system::error_code& err ): err = %s, err.message = %s");
99 fmt % (err ? "true" : "false") % err.message();
100 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 20, fmt.str(), __FILE__, __LINE__);
105 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, err.message(), __FILE__, __LINE__);
109 interrupt_running_flag++;
112 replication &rep_noconst = const_cast<replication &>(rep);
114 if (replication::REPLICATION_SINGLE == rep_noconst.get_status()) {
115 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "replication mode is single.",
117 interrupt_running_flag--;
121 std::stringstream tmp_tcp_ep;
122 tmp_tcp_ep << element.tcp_accept_endpoint;
123 std::stringstream tmp_udp_ep;
124 tmp_udp_ep << element.udp_recv_endpoint;
125 std::stringstream tmp_sorry_ep;
126 tmp_sorry_ep << element.sorry_endpoint;
128 //get replication area
129 unsigned int rep_size = 0;
130 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
131 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
132 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
133 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, REP_BLOCK_SIZE_ERR_MSG,
135 interrupt_running_flag--;
139 //check max data size
140 if ((rep_size * DATA_SIZE) <
141 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
142 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, REP_AREA_SIZE_ERR_MSG,
144 interrupt_running_flag--;
148 //lock replication area
149 rep_noconst.lock(REP_AREA_NAME);
151 //read header value and set loop count
152 unsigned int loop_cnt = rep_header_ptr->data_num;
153 //if data_num over MAX_REPLICATION_DATA_NUM, data_num = 0
154 if (static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt) {
158 //set start pointer(pointer of replication_data)
159 replication_data *rep_data_ptr = reinterpret_cast<replication_data *>(++rep_header_ptr);
162 for (unsigned int i = 0; i < loop_cnt; ++i) {
163 //check equal udpmode and tcp_accept_endpoint
164 if ((rep_data_ptr->udpmode == element.udpmode) &&
165 (0 == strncmp(rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 47))) {
169 //increment data pointer
173 //if it is new data, increment data num.
175 rep_header_ptr = reinterpret_cast<replication_header *>(
176 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
177 ++(rep_header_ptr->data_num);
179 //write replication data
180 rep_data_ptr->udpmode = element.udpmode;
181 strncpy(rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 48);
182 strncpy(rep_data_ptr->udp_endpoint, tmp_udp_ep.str().c_str(), 48);
183 rep_data_ptr->sorry_maxconnection = element.sorry_maxconnection;
184 strncpy(rep_data_ptr->sorry_endpoint, tmp_sorry_ep.str().c_str(), 48);
185 rep_data_ptr->sorry_flag = element.sorry_flag;
186 rep_data_ptr->sorry_fwdmode = element.sorry_fwdmode;
187 rep_data_ptr->qos_up = element.qos_upstream;
188 rep_data_ptr->qos_down = element.qos_downstream;
190 //unlock replication area
191 rep_noconst.unlock(REP_AREA_NAME);
193 if (0 == virtualservice_stop_flag.get()) {
194 //register handle_replication_interrupt
195 replication_timer->expires_from_now(
196 boost::posix_time::milliseconds(param_data.rep_interval));
197 replication_timer->async_wait(boost::bind(
198 &virtualservice_tcp::handle_replication_interrupt,
199 this, boost::asio::placeholders::error));
201 interrupt_running_flag--;
203 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
204 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
205 "out_function: void virtualservice_tcp::handle_replication_interrupt( "
206 "const boost::system::error_code& err )", __FILE__, __LINE__);
211 * read replication data
213 * @param read_replicationdata
217 void l7vs::virtualservice_tcp::read_replicationdata()
219 Logger funclog(LOG_CAT_L7VSD_VIRTUALSERVICE, 22, "function: "
220 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
222 replication &rep_noconst = const_cast<replication &>(rep);
224 if (replication::REPLICATION_SINGLE == rep_noconst.get_status()) {
225 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, "replication mode is single.",
230 unsigned int rep_size = 0;
231 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
232 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
233 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
234 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 3, REP_BLOCK_SIZE_ERR_MSG,
236 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
237 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 23, "out_function: "
238 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
243 //check max data size
244 if ((rep_size * DATA_SIZE) <
245 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
246 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 4, REP_AREA_SIZE_ERR_MSG,
248 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
249 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 24, "out_function: "
250 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
254 //lock replication area
255 rep_noconst.lock(REP_AREA_NAME);
257 //read header value and set loop count
258 unsigned int loop_cnt = rep_header_ptr->data_num;
259 //if data_num over MAX_REPLICATION_DATA_NUM, set data_num = 0
260 if (static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt) {
261 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 5, REP_BLOCK_SIZE_ERR_MSG,
263 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
264 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 25, "out_function: "
265 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
267 rep_header_ptr->data_num = 0;
268 rep_noconst.unlock(REP_AREA_NAME);
272 //set start pointer(pointer of replication_data)
273 replication_data *rep_data_ptr = reinterpret_cast<replication_data *>(++rep_header_ptr);
276 for (unsigned int i = 0; i < loop_cnt; ++i) {
277 //get tcp endpoint data
278 std::string tmpstr = rep_data_ptr->tcp_endpoint;
280 unsigned short portno;
282 portno = boost::lexical_cast<unsigned short>(tmpstr.substr((tmpstr.rfind(":") + 1)));
283 } catch (const boost::bad_lexical_cast &err) {
286 if (tmpstr[0] == '[') {
288 ipaddr = tmpstr.substr(1, (tmpstr.rfind("]") - 1));
291 ipaddr = tmpstr.substr(0, tmpstr.rfind(":"));
293 //check equal udpmode and tcp_accept_endpoint
294 if ((rep_data_ptr->udpmode == element.udpmode) &&
295 (tcp_endpoint_type(boost::asio::ip::address::from_string(ipaddr), portno)
296 == element.tcp_accept_endpoint)) {
297 element.sorry_maxconnection = rep_data_ptr->sorry_maxconnection;
298 tmpstr = rep_data_ptr->sorry_endpoint;
300 portno = boost::lexical_cast<unsigned short>(
301 tmpstr.substr((tmpstr.rfind(":") + 1)));
302 } catch (const boost::bad_lexical_cast &err) {
305 if (tmpstr[0] == '[') {
307 ipaddr = tmpstr.substr(1, (tmpstr.rfind("]") - 1));
310 ipaddr = tmpstr.substr(0, tmpstr.rfind(":"));
312 element.sorry_endpoint =
313 tcp_endpoint_type(boost::asio::ip::address::from_string(ipaddr), portno);
314 element.sorry_flag = rep_data_ptr->sorry_flag;
315 element.sorry_fwdmode = (virtualservice_element::SORRYSERVER_FWDMODE_TAG)(rep_data_ptr->sorry_fwdmode);
316 element.qos_upstream = rep_data_ptr->qos_up;
317 element.qos_downstream = rep_data_ptr->qos_down;
320 //increment data pointer
324 //unlock replication area
325 rep_noconst.unlock(REP_AREA_NAME);
327 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
328 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 26, "out_function: "
329 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
336 * @param handle_accept
340 void l7vs::virtualservice_tcp::handle_accept(const l7vs::session_thread_control *stc_ptr, const boost::system::error_code &err)
342 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
343 boost::format fmt( "in_function: void virtualservice_tcp::handle_accept( "
344 "const boost::shared_ptr<session_thread_control> , "
345 "const boost::system::error_code& err ): err = %s, err.message = %s");
346 fmt % (err ? "true" : "false") % err.message();
347 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 27, fmt.str(), __FILE__, __LINE__);
350 if(unlikely(virtualservice_stop_flag.get())){
354 session_thread_control *stc_ptr_noconst = const_cast<session_thread_control *>(stc_ptr);
356 if( unlikely( err == boost::asio::error::operation_aborted ) ){ // nomal exit case
357 boost::format fmt( "Thread ID[%d] handle accept cancel : %s" );
358 fmt % boost::this_thread::get_id() % err.message();
359 Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 0, fmt.str(), __FILE__, __LINE__ );
362 else if (unlikely(err)) { // register next accept handle when error mode.
363 if(!ssl_virtualservice_mode_flag ){
364 waiting_session->get_client_socket().get_socket().close();
365 acceptor_->async_accept( waiting_session->get_client_socket().get_socket(),
366 boost::bind( &virtualservice_tcp::handle_accept,
369 boost::asio::placeholders::error ) );
371 waiting_session->get_client_ssl_socket().lowest_layer().close();
372 acceptor_->async_accept( waiting_session->get_client_ssl_socket().lowest_layer(),
373 boost::bind( &virtualservice_tcp::handle_accept,
376 boost::asio::placeholders::error ) );
378 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, err.message(), __FILE__, __LINE__);
382 tcp_session *tmp_session = stc_ptr_noconst->get_session().get();
384 if (ssl_file_name != "") {
386 //*-------- DEBUG LOG --------*/
387 if (unlikely(LOG_LV_DEBUG ==
388 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
389 std::stringstream buf;
390 buf << "virtualservice_tcp::handle_accept(): ";
391 buf << "ssl session cache flush before: ";
392 get_ssl_session_cache_info(buf);
393 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
397 //*------ DEBUG LOG END ------*/
399 // ssl session cache flush
400 if (is_session_cache_use == true) {
401 long ssl_cache_num = SSL_CTX_sess_number(sslcontext->impl());
402 if (ssl_cache_num >= session_cache_size) {
407 //*-------- DEBUG LOG --------*/
408 if (unlikely(LOG_LV_DEBUG ==
409 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
410 std::stringstream buf;
411 buf << "virtualservice_tcp::handle_accept(): ";
412 buf << "ssl session cache flush after: ";
413 get_ssl_session_cache_info(buf);
414 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
418 //*------ DEBUG LOG END ------*/
421 // initialize session
422 stc_ptr_noconst->get_session()->initialize();
424 // send access log output ON or OFF message to tcp_session
425 stc_ptr_noconst->session_access_log_output_mode_change(access_log_flag);
427 active_sessions.insert(tmp_session, stc_ptr_noconst);
429 //check sorry flag and status
431 (0 != element.sorry_flag) ||
432 ((0 < element.sorry_maxconnection) && ((active_count.get() >= static_cast<size_t>(element.sorry_maxconnection)))
435 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
436 boost::format fmt("Connection switch Sorry mode. "
437 "active_session.size = %d, active_count.get = %d");
438 fmt % active_sessions.size() % active_count.get();
439 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 30, fmt.str(), __FILE__, __LINE__);
442 stc_ptr_noconst->get_session()->set_virtual_service_message(tcp_session::SORRY_STATE_ENABLE, boost::asio::ip::tcp::endpoint() );
445 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
446 boost::format fmt1("active session thread id = %d");
447 fmt1 % stc_ptr_noconst->get_upthread_id();
448 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 31, fmt1.str(), __FILE__, __LINE__);
449 boost::format fmt2("pool_session.size = %d");
450 fmt2 % pool_sessions.size();
451 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 32, fmt2.str(), __FILE__, __LINE__);
452 boost::format fmt3("active_session.size = %d");
453 fmt3 % active_sessions.size();
454 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 33, fmt3.str(), __FILE__, __LINE__);
455 boost::format fmt4("active_count = %d");
456 fmt4 % active_count.get();
457 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 34, fmt4.str(), __FILE__, __LINE__);
460 stc_ptr_noconst->startupstream();
461 stc_ptr_noconst->startdownstream();
463 //left session is less than the threshold
464 if ((sessionpool_alert_flag == false) &&
465 ((pool_sessions.size() + 1) < param_data.session_pool_alert_on)) {
466 //create trap message
467 trapmessage trap_msg;
468 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
469 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
471 //push the trap message
472 snmpagent::push_trapmessage(trap_msg, err_code);
474 std::string str("Push trap message failed :");
475 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 38, str , __FILE__, __LINE__);
477 //set sessionpool alert flag true
478 sessionpool_alert_flag = true;
481 //waiting, pool_sessions.size become over 1
482 //pick up session from pool
483 session_thread_control* stc_ptr_register_accept;
486 stc_ptr_register_accept = pool_sessions.pop();
487 if( stc_ptr_register_accept ) break;
488 else if( pool_sessions.empty() ) dispatcher->poll();
489 timespec ts = { 0, 50 };
490 nanosleep( &ts, NULL );
493 //session add wait_sessions
494 boost::mutex::scoped_lock up_wait_lk(stc_ptr_register_accept->get_upthread_mutex());
495 boost::mutex::scoped_lock down_wait_lk(stc_ptr_register_accept->get_downthread_mutex());
497 waiting_session = stc_ptr_register_accept->get_session().get();
499 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
500 boost::format fmt1("active session thread id = %d");
501 fmt1 % stc_ptr_register_accept->get_upthread_id();
502 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 35, fmt1.str(), __FILE__, __LINE__);
503 boost::format fmt2("pool_session.size = %d");
504 fmt2 % pool_sessions.size();
505 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 36, fmt2.str(), __FILE__, __LINE__);
506 boost::format fmt3("active_session.size = %d");
507 fmt3 % active_sessions.size();
508 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 37, fmt3.str(), __FILE__, __LINE__);
509 boost::format fmt4("active_count = %d");
510 fmt4 % active_count.get();
511 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 38, fmt4.str(), __FILE__, __LINE__);
514 //register accept event handler
515 if (!ssl_virtualservice_mode_flag) {
516 acceptor_->async_accept(waiting_session->get_client_socket().get_socket(),
517 boost::bind(&virtualservice_tcp::handle_accept,
519 stc_ptr_register_accept,
520 boost::asio::placeholders::error));
523 acceptor_->async_accept(waiting_session->get_client_ssl_socket().lowest_layer(),
524 boost::bind(&virtualservice_tcp::handle_accept,
526 stc_ptr_register_accept,
527 boost::asio::placeholders::error));
530 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
531 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 39,
533 "void virtualservice_tcp::handle_accept( "
534 "const boost::shared_ptr<session_thread_control> , "
535 "const boost::system::error_code& err )", __FILE__, __LINE__);
540 * initialize virtualservice(TCP)
545 void l7vs::virtualservice_tcp::initialize(l7vs::error_code &err)
547 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
548 boost::format formatter("in_function: void virtualservice_tcp::initialize( "
549 "l7vs::error_code& err )");
550 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, formatter.str(), __FILE__, __LINE__);
552 if (pool_sessions.size() != 0) {
553 err.setter(true, "VirtualService already initialized.");
554 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
555 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
556 "l7vs::error_code& err ): err = %s, err.message = %s");
557 formatter % (err ? "true" : "false") % err.get_message();
558 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 41, formatter.str(),
564 //load parameter value
567 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
568 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
569 "l7vs::error_code& err ): err = %s, err.message = %s");
570 formatter % (err ? "true" : "false") % err.get_message();
571 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 42, formatter.str(),
577 // access log flag and access log file name setting contents check.
578 if (element.access_log_flag == 1 && element.access_log_file_name == "") {
579 boost::format formatter("access log file name not set error");
580 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 3, formatter.str(), __FILE__, __LINE__);
581 err.setter(true, "access log file name not set error");
585 logger_implement_access *access_log_instance = NULL;
586 // access log instance create.
587 if (element.access_log_file_name != "") {
589 = logger_access_manager::getInstance().find_logger_implement_access(
590 element.access_log_file_name,
591 element.access_log_rotate_arguments,
593 if (access_log_instance == NULL) {
594 boost::format formatter("access logger Instance acquisition err = %s, "
595 "err.message = %s ");
596 formatter % (err ? "true" : "false") % err.get_message();
597 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 4, formatter.str(),
599 err.setter(true, "access log class instance create failed");
605 boost::asio::ip::address address = element.tcp_accept_endpoint.address();
606 #ifdef SCHED_SETAFFINITY
607 vsnic_cpumask = get_cpu_mask(address);
608 rsnic_cpumask = get_cpu_mask(param_data.nic_realserver_side);
612 boost::system::error_code acceptor_err;
613 acceptor_->open(element.tcp_accept_endpoint.protocol(), acceptor_err);
615 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 5, acceptor_err.message(),
617 err.setter(true, acceptor_err.message());
620 acceptor_->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), acceptor_err);
622 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 6, acceptor_err.message(),
624 err.setter(true, acceptor_err.message());
627 if (likely(address.is_v6())) {
628 boost::asio::ip::v6_only option(true);
629 acceptor_->set_option(option, acceptor_err);
631 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 7, acceptor_err.message(),
633 err.setter(true, acceptor_err.message());
637 acceptor_->bind(element.tcp_accept_endpoint, acceptor_err);
639 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 8, acceptor_err.message(),
641 err.setter(true, acceptor_err.message());
645 //read replication data
646 read_replicationdata();
648 //load protocol module
649 protomod = protocol_module_control::getInstance().load_module(element.protocol_module_name);
650 if (NULL == protomod) {
652 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 9, PROTOMOD_LOAD_ERROR_MSG,
654 err.setter(true, PROTOMOD_LOAD_ERROR_MSG);
655 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
656 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
657 "l7vs::error_code& err ): err = %s, err.message = %s");
658 formatter % (err ? "true" : "false") % err.get_message();
659 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 43, formatter.str(),
664 //Protocol Module Initialize
665 protomod->init_logger_functions(
666 boost::bind(&Logger::getLogLevel, LOG_CAT_PROTOCOL),
667 boost::bind(&Logger::putLogFatal, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
668 boost::bind(&Logger::putLogError, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
669 boost::bind(&Logger::putLogWarn, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
670 boost::bind(&Logger::putLogInfo, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
671 boost::bind(&Logger::putLogDebug, LOG_CAT_PROTOCOL, _1, _2, _3, _4));
672 protomod->initialize(
673 boost::bind(&virtualservice_tcp::rs_list_begin, this),
674 boost::bind(&virtualservice_tcp::rs_list_end, this),
675 boost::bind(&virtualservice_tcp::rs_list_next, this, _1),
676 boost::bind(&virtualservice_tcp::rs_list_lock, this),
677 boost::bind(&virtualservice_tcp::rs_list_unlock, this));
678 protomod->init_replication_functions(
679 boost::bind(&virtualservice_tcp::replication_pay_memory, this, _1, _2),
680 boost::bind(&virtualservice_tcp::replication_area_lock, this, element.protocol_module_name),
681 boost::bind(&virtualservice_tcp::replication_area_unlock, this, element.protocol_module_name),
682 element.tcp_accept_endpoint,
683 element.udp_recv_endpoint);
684 tcp_schedule_func_type sched_rs_func = boost::bind(
685 &virtualservice_tcp::schedule_rs, this, _1, _2, _3, _4, _5);
686 protomod->register_schedule(sched_rs_func);
688 protocol_module_base::check_message_result pm_result;
690 pm_result = protomod->check_parameter(element.protocol_args);
691 if (!pm_result.flag) {
692 err.setter(true, "Protocol Module argument error.");
693 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
694 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
695 "l7vs::error_code& err ): err = %s, err.message = %s");
696 formatter % (err ? "true" : "false") % err.get_message();
697 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 44, formatter.str(),
702 pm_result = protomod->set_parameter(element.protocol_args);
703 if (!pm_result.flag) {
704 err.setter(true, "Protocol Module argument error.");
705 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
706 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
707 "l7vs::error_code& err ): err = %s, err.message = %s");
708 formatter % (err ? "true" : "false") % err.get_message();
709 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 45, formatter.str(),
715 protomod->get_option_info(protocol_module_for_indication_options);
716 element.protocol_module_for_indication_options = protocol_module_for_indication_options;
718 //load schedule module
719 schedmod = schedule_module_control::getInstance().load_module(element.schedule_module_name);
720 if (NULL == schedmod) {
722 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 10, SCHEDMOD_LOAD_ERROR_MSG,
724 err.setter(true, SCHEDMOD_LOAD_ERROR_MSG);
725 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
726 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
727 "l7vs::error_code& err ) : err = %s, err.message = %s");
728 formatter % (err ? "true" : "false") % err.get_message();
729 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 46, formatter.str(),
734 //Schedule Module Initialize
735 schedmod->init_logger_functions(
736 boost::bind(&Logger::getLogLevel, LOG_CAT_SCHEDULE),
737 boost::bind(&Logger::putLogFatal, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
738 boost::bind(&Logger::putLogError, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
739 boost::bind(&Logger::putLogWarn, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
740 boost::bind(&Logger::putLogInfo, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
741 boost::bind(&Logger::putLogDebug, LOG_CAT_SCHEDULE, _1, _2, _3, _4));
742 schedmod->initialize();
743 schedmod->init_replication_functions(
744 boost::bind(&virtualservice_tcp::replication_pay_memory, this, _1, _2),
745 boost::bind(&virtualservice_tcp::replication_area_lock, this, element.schedule_module_name),
746 boost::bind(&virtualservice_tcp::replication_area_unlock, this, element.schedule_module_name),
747 element.tcp_accept_endpoint,
748 element.udp_recv_endpoint);
750 // access log flag set
751 access_log_flag = false;
752 if (element.access_log_flag == 1) {
753 access_log_flag = true;
756 // access log rotation information set.
757 if (element.access_log_rotate_key_info == "") {
758 element.access_log_rotate_key_info = "none";
759 element.access_log_rotate_verbose_info = logger_access_manager::getInstance().get_rotate_default_verbose_displayed_contents();
761 element.access_log_rotate_verbose_info = element.access_log_rotate_key_info;
763 access_log_file_name = element.access_log_file_name;
764 access_log_rotate_arguments = element.access_log_rotate_arguments;
767 ssl_virtualservice_mode_flag = false;
768 ssl_file_name = element.ssl_file_name;
769 if (ssl_file_name != "") {
770 ssl_file_name = element.ssl_file_name;
772 if (unlikely(!get_ssl_parameter())) {
774 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 11, "get ssl parameter failed",
776 err.setter(true, "get ssl parameter failed");
779 // set SSL configuration
780 if (unlikely(!set_ssl_config())) {
782 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 12, "set ssl config failed",
784 err.setter(true, "set ssl config failed");
787 ssl_virtualservice_mode_flag = true;
793 //create session pool
795 for (int i = 0; i < param_data.session_pool_size; ++i) {
797 tcp_session *sess = new tcp_session(*this,
800 element.tcp_accept_endpoint,
801 ssl_virtualservice_mode_flag,
803 is_session_cache_use,
805 access_log_instance);
806 session_result_message result = sess->initialize();
807 if (result.flag == true) {
808 err.setter(result.flag, result.message);
809 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
810 boost::format formatter("out_function: "
811 "void virtualservice_tcp::initialize( "
812 "l7vs::error_code& err ): err = %s, "
814 formatter % (err ? "true" : "false") % err.get_message();
815 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 47,
816 formatter.str(), __FILE__, __LINE__);
820 session_thread_control *p_stc = new session_thread_control(
821 sess, vsnic_cpumask, rsnic_cpumask, -1);
823 p_stc->start_thread();
824 while (!pool_sessions.push(p_stc)) {}
827 LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "error, create session.",
830 err.setter(true, "error, create session.");
833 l7vs::error_code finalize_err;
834 finalize_err.setter(false, "");
835 finalize(finalize_err);
837 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
838 boost::format formatter("out_function: "
839 "void virtualservice_tcp::initialize( "
840 "l7vs::error_code& err ): err = %s, err.message = %s");
841 formatter % (err ? "true" : "false") % err.get_message();
842 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 48, formatter.str(),
848 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
849 boost::format fmt1("pool_session.size = %d");
850 fmt1 % pool_sessions.size();
851 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 49, fmt1.str(),
853 boost::format fmt2("active_session.size = %d");
854 fmt2 % active_sessions.size();
855 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 50, fmt2.str(),
860 err.setter(false, "");
862 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
863 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
864 "l7vs::error_code& err ): err = %s, err.message = %s");
865 formatter % (err ? "true" : "false") % err.get_message();
866 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 51, formatter.str(),
872 * finalize virtualservice(TCP)
877 void l7vs::virtualservice_tcp::finalize(l7vs::error_code &err)
879 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
880 boost::format formatter("in_function: void virtualservice_tcp::finalize( "
881 "l7vs::error_code& err )");
882 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 52, formatter.str(),
884 boost::format fmt1("pool_session.size = %d");
885 fmt1 % pool_sessions.size();
886 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 53, fmt1.str(),
888 boost::format fmt2("active_session.size = %d");
889 fmt2 % active_sessions.size();
890 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 54, fmt2.str(),
894 //release sessions[i]->join();
895 while (!pool_sessions.empty()) {
896 session_thread_control *stc = pool_sessions.pop();
899 boost::mutex::scoped_lock upthread_wait(stc->get_upthread_mutex());
900 boost::mutex::scoped_lock downthread_wait(stc->get_downthread_mutex());
904 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
905 boost::format fmt("join pool session: pool_sessions.size = %d");
906 fmt % pool_sessions.size();
907 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 55, fmt.str(),
911 //waiting session delete
912 delete waiting_session;
913 waiting_session = NULL;
915 //unload ProtocolModule
917 //finalize ProtocolModule
918 protomod->finalize();
919 //unload ProtocolModule
920 protocol_module_control::getInstance().unload_module(protomod);
923 //unload ScheduleModule
925 schedule_module_control::getInstance().unload_module(schedmod);
929 active_sessions.clear();
930 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
931 boost::format fmt1("pool_session.size = %d");
932 fmt1 % pool_sessions.size();
933 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 56, fmt1.str(), __FILE__, __LINE__);
934 boost::format fmt2("active_session.size = %d");
935 fmt2 % active_sessions.size();
936 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 57, fmt2.str(), __FILE__, __LINE__);
939 //clear replication_data
940 bool replication_status = true;
941 replication &rep_noconst = const_cast<replication &>(rep);
943 if (replication::REPLICATION_SINGLE != rep_noconst.get_status()) {
944 unsigned int rep_size = 0;
945 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
946 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
947 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
948 err.setter(true, REP_BLOCK_SIZE_ERR_MSG);
949 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 6, REP_BLOCK_SIZE_ERR_MSG,
951 replication_status = false;
954 //check max data size
955 if ((rep_size * DATA_SIZE) <
956 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
957 err.setter(true, REP_AREA_SIZE_ERR_MSG);
958 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 7, REP_AREA_SIZE_ERR_MSG,
960 replication_status = false;
962 if ((NULL != rep_header_ptr) && (replication_status)) {
963 //lock replication area
964 rep_noconst.lock(REP_AREA_NAME);
966 rep_header_ptr->data_num = 0;
967 //unlock replication area
968 rep_noconst.unlock(REP_AREA_NAME);
972 //vsd.release_virtual_service( element );
973 if (access_log_file_name != "") {
974 // erase access log instance.
975 logger_access_manager::getInstance().erase_logger_implement_access(access_log_file_name, err);
977 boost::format fmt("access logger instance erase err:%s");
978 fmt % err.get_message();
979 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 8,
985 vsd.release_virtual_service(element);
987 err.setter(false, "");
989 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
990 boost::format formatter("out_function: void virtualservice_tcp::finalize( "
991 "l7vs::error_code& err ): err = %s, err.message = %s");
992 formatter % (err ? "true" : "false") % err.get_message();
993 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 58, formatter.str(), __FILE__, __LINE__);
999 * equal compare virtualservice(TCP)
1001 * @param virtualservice_base
1002 * @return bool ( true = equal )
1004 bool l7vs::virtualservice_tcp::operator==(const l7vs::virtualservice_base &in)
1006 boost::format formatter("function: void virtualservice_tcp::operator==( "
1007 "const l7vs::virtualservice_base& in )");
1008 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 59, formatter.str(), __FILE__, __LINE__);
1010 virtualservice_base &vs = const_cast<virtualservice_base &>(in);
1011 return ((element.tcp_accept_endpoint == vs.get_element().tcp_accept_endpoint)
1012 && (element.udpmode == vs.get_element().udpmode));
1016 * not-equal compare virtualservice(TCP)
1018 * @param virtualservice_base
1019 * @return bool ( true = not-equal )
1021 bool l7vs::virtualservice_tcp::operator!=(const l7vs::virtualservice_base &in)
1023 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1024 boost::format formatter("in/out_function: void virtualservice_tcp::operator!=( "
1025 "const l7vs::virtualservice_base& in )");
1026 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 60, formatter.str(), __FILE__, __LINE__);
1028 virtualservice_base &vs = const_cast<virtualservice_base &>(in);
1029 return ((element.tcp_accept_endpoint != vs.get_element().tcp_accept_endpoint)
1030 || (element.udpmode != vs.get_element().udpmode));
1034 * add VirtualService( not-implement )
1036 * @param virtualservice_element
1040 void l7vs::virtualservice_tcp::set_virtualservice(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1042 err.setter(false, "");
1046 * edit VirtualService
1048 * @param virtualservice_element
1052 void l7vs::virtualservice_tcp::edit_virtualservice(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1054 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1055 boost::format formatter("in_function: void virtualservice_tcp::edit_virtualservice( "
1056 "const l7vs::virtualservice_element& in,"
1057 "l7vs::error_code& err ): dump in ");
1058 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 61, formatter.str(), __FILE__, __LINE__);
1061 virtualservice_element &elem = const_cast<virtualservice_element &>(in);
1062 if ((element.udpmode != elem.udpmode) ||
1063 (element.tcp_accept_endpoint != elem.tcp_accept_endpoint) ||
1064 (element.protocol_module_name != elem.protocol_module_name)) {
1065 err.setter(true, "Virtual Service does not exist.");
1066 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1067 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1068 "const l7vs::virtualservice_element& in,"
1069 "l7vs::error_code& err ): err = %s, err.message = %s");
1070 formatter % (err ? "true" : "false") % err.get_message();
1071 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 62, formatter.str(),
1072 __FILE__, __LINE__);
1077 //if change ScheduleModule Name, unload old ScheduleModule and load new ScheduleModule
1078 if ((element.schedule_module_name != elem.schedule_module_name) && ("" != elem.schedule_module_name)) {
1079 schedule_module_control::getInstance().unload_module(schedmod);
1080 schedmod = schedule_module_control::getInstance().load_module(elem.schedule_module_name);
1081 if (NULL == schedmod) {
1083 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 13, SCHEDMOD_LOAD_ERROR_MSG,
1084 __FILE__, __LINE__);
1085 err.setter(true, SCHEDMOD_LOAD_ERROR_MSG);
1086 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1087 boost::format formatter("out_function: "
1088 "void virtualservice_tcp::edit_virtualservice( "
1089 "const l7vs::virtualservice_element& in,"
1090 "l7vs::error_code& err ): err = %s, err.message = %s");
1091 formatter % (err ? "true" : "false") % err.get_message();
1092 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 63, formatter.str(),
1093 __FILE__, __LINE__);
1097 element.schedule_module_name = elem.schedule_module_name;
1100 //additional PM options(for protomod_url)
1101 protocol_module_base::check_message_result result;
1102 if( NULL != protomod ){
1103 result = protomod->add_parameter( elem.protocol_args );
1105 for( size_t i = 0; i < elem.protocol_args.size(); ++i ){
1106 element.protocol_args.push_back( elem.protocol_args[i] );
1109 err.setter( true, result.message );
1110 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1111 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1112 "const l7vs::virtualservice_element& in,"
1113 "l7vs::error_code& err ): err = %s, err.message = %s");
1114 formatter % ( err ? "true" : "false") % err.get_message();
1115 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 64, formatter.str(),
1116 __FILE__, __LINE__ );
1122 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 14, PROTOMOD_LOAD_ERROR_MSG,
1123 __FILE__, __LINE__ );
1124 err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
1125 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1126 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1127 "const l7vs::virtualservice_element& in,"
1128 "l7vs::error_code& err ): err = %s, err.message = %s");
1129 formatter % ( err ? "true" : "false") % err.get_message();
1130 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 65, formatter.str(),
1131 __FILE__, __LINE__ );
1138 if (ULLONG_MAX == elem.qos_upstream) {
1139 element.qos_upstream = 0ULL;
1140 } else if (0ULL != elem.qos_upstream) {
1141 element.qos_upstream = elem.qos_upstream;
1144 if (ULLONG_MAX == elem.qos_downstream) {
1145 element.qos_downstream = 0ULL;
1146 } else if (0ULL != elem.qos_downstream) {
1147 element.qos_downstream = elem.qos_downstream;
1149 //sorry_maxconnection;
1150 if (LLONG_MAX == elem.sorry_maxconnection) {
1151 element.sorry_maxconnection = 0;
1152 } else if (0 != elem.sorry_maxconnection) {
1153 element.sorry_maxconnection = elem.sorry_maxconnection;
1156 if (INT_MAX == elem.sorry_flag) {
1157 element.sorry_flag = 0;
1158 } else if (0 != elem.sorry_flag) {
1159 element.sorry_flag = 1;
1162 if (virtualservice_element::FWD_NONE != elem.sorry_fwdmode) {
1163 element.sorry_fwdmode = elem.sorry_fwdmode;
1166 //if endpoint of SorryServer equal 255.255.255.255:0,not update
1167 //if equal endpoint 255.255.255.255:0, clear sorry parameters
1168 if (elem.sorry_endpoint ==
1169 boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("255.255.255.255"), (0))) {
1170 element.sorry_endpoint = boost::asio::ip::tcp::endpoint(
1171 boost::asio::ip::address::from_string("0.0.0.0"), (0));
1172 element.sorry_maxconnection = 0LL;
1173 element.sorry_flag = false;
1174 active_sessions.do_all(boost::bind(&session_thread_control::session_sorry_disable, _1));
1176 if (elem.sorry_endpoint != boost::asio::ip::tcp::endpoint(
1177 boost::asio::ip::address::from_string("0.0.0.0"), (0))) {
1178 element.sorry_endpoint = elem.sorry_endpoint;
1180 active_sessions.do_all(boost::bind(
1181 &session_thread_control::session_sorry_mode_change, _1, elem.sorry_flag));
1184 if (elem.access_log_flag != -1) {
1185 // access log flag ON and access log filename not set.
1186 if (elem.access_log_flag == 1 && element.access_log_file_name == "") {
1188 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 15, SCHEDMOD_LOAD_ERROR_MSG,
1189 __FILE__, __LINE__);
1190 err.setter(true, "access log flag change err.");
1194 // access log flag check and send access log output ON or OFF message to tcp_session
1195 element.access_log_flag = elem.access_log_flag;
1196 if (elem.access_log_flag == 1 && access_log_flag == false) {
1197 active_sessions.do_all(boost::bind(
1198 &session_thread_control::session_accesslog_output_mode_on, _1));
1199 access_log_flag = true;
1200 } else if (elem.access_log_flag == 0 && access_log_flag == true) {
1201 active_sessions.do_all(boost::bind(
1202 &session_thread_control::session_accesslog_output_mode_off, _1));
1203 access_log_flag = false;
1207 err.setter(false, "");
1209 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1210 boost::format formatter("out_function: void virtualservice_tcp::set_virtualservice( "
1211 "const l7vs::virtualservice_element& in,"
1212 "l7vs::error_code& err ): err = %s, err.message = %s");
1213 formatter % (err ? "true" : "false") % err.get_message();
1214 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 66, formatter.str(), __FILE__, __LINE__);
1221 * @param virtualservice_element
1225 void l7vs::virtualservice_tcp::add_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1227 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1228 boost::format formatter("in_function: void virtualservice_tcp::add_realserver( "
1229 "const l7vs::virtualservice_element& in,"
1230 "l7vs::error_code& err )");
1231 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 67, formatter.str(), __FILE__, __LINE__);
1234 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1236 //check equal virtualservice
1237 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1238 err.setter(true, "Virtual Service does not exist.");
1239 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1240 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1241 "const l7vs::virtualservice_element& in,"
1242 "l7vs::error_code& err ): err = %s, err.message = %s");
1243 formatter % (err ? "true" : "false") % err.get_message();
1244 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 68, formatter.str(),
1245 __FILE__, __LINE__);
1250 if (in.realserver_vector.size() == 0U) {
1251 err.setter(true, ".");
1252 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1253 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1254 "const l7vs::virtualservice_element& in,"
1255 "l7vs::error_code& err ): err = %s, err.message = %s");
1256 formatter % (err ? "true" : "false") % err.get_message();
1257 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 69, formatter.str(),
1258 __FILE__, __LINE__);
1262 //lock rs_list_ref_count_inc_mutex
1263 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1265 //waiting, rs_list_ref_count become 0
1266 while (rs_list_ref_count != 0ULL) {
1267 boost::this_thread::sleep(
1268 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1272 //check duplication realserver
1273 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1274 itr != in_element.realserver_vector.end();
1276 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1277 rs_itr != rs_list.end(); ++rs_itr) {
1278 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1279 err.setter(true, "Real Server already exist.");
1280 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1281 boost::format formatter("out_function: "
1282 "void virtualservice_tcp::add_realserver( "
1283 "const l7vs::virtualservice_element& in,"
1284 "l7vs::error_code& err ): err = %s, err.message = %s");
1285 formatter % (err ? "true" : "false") % err.get_message();
1286 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 70,
1287 formatter.str(), __FILE__, __LINE__);
1294 //pause active sessions
1295 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_on, _1));
1298 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1299 itr != in_element.realserver_vector.end();
1302 rs.tcp_endpoint = itr->tcp_endpoint;
1303 rs.udp_endpoint = itr->udp_endpoint;
1304 rs.weight = itr->weight;
1305 rs.fwdmode = itr->fwdmode;
1306 rs_list.push_back(rs);
1309 //run active sessions
1310 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1312 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1313 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1314 "const l7vs::virtualservice_element& in,"
1315 "l7vs::error_code& err ): err = %s, err.message = %s");
1316 formatter % (err ? "true" : "false") % err.get_message();
1317 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 71, formatter.str(), __FILE__, __LINE__);
1324 * @param virtualservice_element
1328 void l7vs::virtualservice_tcp::edit_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1330 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1331 boost::format formatter("in_function: void virtualservice_tcp::edit_realserver( "
1332 "const l7vs::virtualservice_element& in,"
1333 "l7vs::error_code& err )");
1334 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 72, formatter.str(), __FILE__, __LINE__);
1336 //check equal virtualservice
1337 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1338 err.setter(true, "Virtual Service does not exist.");
1339 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1340 boost::format formatter("out_function: void virtualservice_tcp::edit_realserver( "
1341 "const l7vs::virtualservice_element& in,"
1342 "l7vs::error_code& err ): err = %s, err.message = %s");
1343 formatter % (err ? "true" : "false") % err.get_message();
1344 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 73, formatter.str(),
1345 __FILE__, __LINE__);
1350 //lock rs_list_ref_count_inc_mutex
1351 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1353 //waiting, rs_list_ref_count become 0
1354 while (rs_list_ref_count != 0ULL) {
1355 boost::this_thread::sleep(
1356 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1360 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1362 //check is exist realserver
1363 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1364 itr != in_element.realserver_vector.end();
1366 bool exist_flag = false;
1367 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1368 rs_itr != rs_list.end(); ++rs_itr) {
1369 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1374 err.setter(true, "Real Server does not exist.");
1375 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1376 boost::format formatter("out_function: "
1377 "void virtualservice_tcp::edit_realserver( "
1378 "const l7vs::virtualservice_element& in,"
1379 "l7vs::error_code& err ): err = %s, err.message = %s");
1380 formatter % (err ? "true" : "false") % err.get_message();
1381 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 74, formatter.str(),
1382 __FILE__, __LINE__);
1388 //pause active sessions
1389 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_on, _1));
1392 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1393 itr != in_element.realserver_vector.end();
1395 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1396 rs_itr != rs_list.end(); ++rs_itr) {
1397 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1398 rs_itr->udp_endpoint = itr->udp_endpoint;
1400 if (itr->weight != -1) {
1401 rs_itr->weight = itr->weight;
1403 if (itr->fwdmode != realserver_element::FWD_NONE) {
1404 rs_itr->fwdmode = itr->fwdmode;
1410 //run active sessions
1411 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1413 err.setter(false, "");
1414 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1415 boost::format formatter("out_function: void virtualservice_tcp::edit_realserver( "
1416 "const l7vs::virtualservice_element& in,"
1417 "l7vs::error_code& err ): err = %s, err.message = %s");
1418 formatter % (err ? "true" : "false") % err.get_message();
1419 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 75, formatter.str(), __FILE__, __LINE__);
1426 * @param virtualservice_element
1430 void l7vs::virtualservice_tcp::del_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1432 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1433 boost::format formatter("in_function: void virtualservice_tcp::del_realserver( "
1434 "const l7vs::virtualservice_element& in,"
1435 "l7vs::error_code& err )");
1436 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 76, formatter.str(), __FILE__, __LINE__);
1439 //check equal virtualservice
1440 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1441 err.setter(true, "Virtual Service is not equal.");
1442 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1443 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1444 "const l7vs::virtualservice_element& in,"
1445 "l7vs::error_code& err ): err = %s, err.message = %s");
1446 formatter % (err ? "true" : "false") % err.get_message();
1447 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 77, formatter.str(),
1448 __FILE__, __LINE__);
1453 //lock rs_list_ref_count_inc_mutex
1454 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1456 //waiting, rs_list_ref_count become 0
1457 while (rs_list_ref_count != 0ULL) {
1458 boost::this_thread::sleep(
1459 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1463 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1465 //check is exist realserver
1466 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1467 itr != in_element.realserver_vector.end();
1469 bool exist_flag = false;
1470 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1471 rs_itr != rs_list.end(); ++rs_itr) {
1472 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1477 err.setter(true, "Real Server does not exist.");
1478 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1479 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1480 "const l7vs::virtualservice_element& in,"
1481 "l7vs::error_code& err ): err = %s, err.message = %s");
1482 formatter % (err ? "true" : "false") % err.get_message();
1483 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 78, formatter.str(),
1484 __FILE__, __LINE__);
1490 //pause active sessions
1491 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_on, _1));
1494 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1495 itr != in_element.realserver_vector.end();
1497 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1498 rs_itr != rs_list.end(); ++rs_itr) {
1499 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1500 rs_list.erase(rs_itr);
1501 active_sessions.do_all( boost::bind( &session_thread_control::session_realserver_remove, _1, rs_itr->tcp_endpoint ) );
1507 //run active sessions
1508 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1510 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1511 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1512 "const l7vs::virtualservice_element& in,"
1513 "l7vs::error_code& err ): err = %s, err.message = %s");
1514 formatter % (err ? "true" : "false") % err.get_message();
1515 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 79, formatter.str(), __FILE__, __LINE__);
1520 * main loop of virtualservice(TCP)
1525 void l7vs::virtualservice_tcp::run()
1527 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function: void virtualservice_tcp::run()",
1528 __FILE__, __LINE__);
1530 if (pool_sessions.size() == 0) {
1531 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.",
1532 __FILE__, __LINE__);
1535 boost::asio::socket_base::receive_buffer_size option(8192 * 192);
1536 acceptor_->set_option(option);
1537 //set socket option TCP_DEFER_ACCEPT
1538 if (defer_accept_opt) {
1539 size_t len = sizeof(defer_accept_val);
1540 int err = ::setsockopt(acceptor_->native(), IPPROTO_TCP, TCP_DEFER_ACCEPT, &defer_accept_val, len);
1541 if (unlikely(err)) {
1543 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
1544 "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__);
1548 acceptor_->listen();
1550 //left session is less than the threshold
1551 if ((sessionpool_alert_flag == false) &&
1552 (pool_sessions.size() < param_data.session_pool_alert_on)) {
1553 //create trap message
1554 trapmessage trap_msg;
1555 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
1556 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
1557 error_code err_code;
1558 //push the trap message
1559 snmpagent::push_trapmessage(trap_msg, err_code);
1561 std::string msg("Push trap message failed.");
1562 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, msg, __FILE__, __LINE__);
1565 //set sessionpool alert flag true
1566 sessionpool_alert_flag = true;
1569 //switch active a session
1570 session_thread_control *stc_ptr;
1572 stc_ptr = pool_sessions.pop();
1576 waiting_session = stc_ptr->get_session().get();
1578 if (!ssl_virtualservice_mode_flag) {
1579 acceptor_->async_accept( waiting_session->get_client_socket().get_socket(),
1580 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1581 boost::asio::placeholders::error));
1583 acceptor_->async_accept( waiting_session->get_client_ssl_socket().lowest_layer(),
1584 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1585 boost::asio::placeholders::error));
1587 //register timer event handler
1588 calc_bps_timer->expires_from_now(boost::posix_time::milliseconds(param_data.bps_interval));
1589 calc_bps_timer->async_wait(boost::bind(&virtualservice_tcp::handle_throughput_update,
1590 this, boost::asio::placeholders::error));
1592 //register handle_replication_interrupt
1593 replication_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1594 replication_timer->async_wait(boost::bind(&virtualservice_tcp::handle_replication_interrupt,
1595 this, boost::asio::placeholders::error));
1596 //register handle_protomod_replication
1597 protomod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1598 protomod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_protomod_replication,
1599 this, boost::asio::placeholders::error));
1600 //register handle_schedmod_replication
1601 schedmod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1602 schedmod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_schedmod_replication,
1603 this, boost::asio::placeholders::error));
1605 //run dispatcher(start io_service loop)
1606 work.reset(new boost::asio::io_service::work(*dispatcher));
1607 boost::thread_group dispatcher_thread_group;
1609 for(int i = 0; i < IO_SERVICE_THREADS_NUM; i++){
1610 dispatcher_thread_group.create_thread(boost::bind(&boost::asio::io_service::run, dispatcher));
1613 //join dispatcher_thread_group when virtualservice_tcp::stop() executed.
1614 dispatcher_thread_group.join_all();
1616 //stop all active sessions
1618 active_sessions.do_all(boost::bind(&session_thread_control::session_stop, _1));
1628 void l7vs::virtualservice_tcp::stop()
1630 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function: void virtualservice_tcp::stop()",
1631 __FILE__, __LINE__);
1633 boost::system::error_code err;
1634 virtualservice_stop_flag++;
1635 while (interrupt_running_flag.get()) {
1636 boost::this_thread::yield();
1639 acceptor_->close(err);
1641 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__);
1646 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1 ) );
1647 active_sessions.do_all( boost::bind( &session_thread_control::session_stop, _1 ) );
1648 while (active_sessions.size()) {
1649 boost::this_thread::yield();
1653 calc_bps_timer->cancel();
1654 replication_timer->cancel();
1655 protomod_rep_timer->cancel();
1656 schedmod_rep_timer->cancel();
1659 dispatcher->reset();
1665 * increment active-connection count
1670 void l7vs::virtualservice_tcp::connection_active(const boost::asio::ip::tcp::endpoint &in)
1672 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1673 boost::format formatter("in_function: void virtualservice_tcp::connection_active( "
1674 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1676 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__);
1679 for (std::list<realserver>::iterator itr = rs_list.begin();
1680 itr != rs_list.end();
1682 if (itr->tcp_endpoint == in) {
1683 itr->increment_active();
1690 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1691 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 83, "out_function: "
1692 "void virtualservice_tcp::connection_active()", __FILE__, __LINE__);
1697 * increment in-active-connection (and decrement active-connection count)
1702 void l7vs::virtualservice_tcp::connection_inactive(const boost::asio::ip::tcp::endpoint &in)
1704 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1705 boost::format formatter("in_function: void virtualservice_tcp::connection_inactive( "
1706 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1708 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__);
1711 for (std::list<realserver>::iterator itr = rs_list.begin();
1712 itr != rs_list.end();
1714 if (itr->tcp_endpoint == in) {
1715 itr->decrement_active();
1716 itr->increment_inact();
1723 //left session is more than the release threshold
1724 if ((sessionpool_alert_flag == true) &&
1725 ((pool_sessions.size() + 1 ) > param_data.session_pool_alert_off)) {
1726 //create trap message
1727 trapmessage trap_msg;
1728 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_OFF;
1729 trap_msg.message = "TRAP00020012,Warning release: The left-session has exceeded the release threshold of left-session warning.";
1730 error_code err_code;
1731 //push the trap message
1732 snmpagent::push_trapmessage(trap_msg, err_code);
1734 std::string msg("Push trap message failed.");
1735 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 39, msg, __FILE__, __LINE__);
1738 //set sessionpool alert flag true
1739 sessionpool_alert_flag = false;
1742 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1743 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 85, "out_function: "
1744 "void virtualservice_tcp::connection_inactive()", __FILE__, __LINE__);
1754 void l7vs::virtualservice_tcp::release_session(const tcp_session *session_ptr)
1756 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1757 boost::format funclog_fmt("in_function: void virtualservice_tcp::release_session( "
1758 "const tcp_session* session_ptr ): session_ptr = %d");
1759 funclog_fmt % session_ptr;
1760 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 86, funclog_fmt.str(), __FILE__, __LINE__);
1763 session_thread_control *stc_ptr = active_sessions.find(session_ptr);
1764 if (unlikely(NULL == stc_ptr)) {
1765 boost::format fmt("session release fail: "
1766 "active_sessions.find( const tcp_session* session_ptr = %d )");
1768 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*XXX*/999, fmt.str(), __FILE__, __LINE__);
1769 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1770 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 88, "out_function: "
1771 "void virtualservice_tcp::release_session( "
1772 "const boost::thread::id thread_id )", __FILE__, __LINE__);
1777 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1778 boost::format fmt1("pool_session.size = %d");
1779 fmt1 % pool_sessions.size();
1780 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 89, fmt1.str(), __FILE__, __LINE__);
1781 boost::format fmt2("active_session.size = %d");
1782 fmt2 % active_sessions.size();
1783 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 90, fmt2.str(), __FILE__, __LINE__);
1784 boost::format fmt3("active_count = %d");
1785 fmt3 % active_count.get();
1786 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 91, fmt3.str(), __FILE__, __LINE__);
1788 active_sessions.erase(session_ptr);
1790 while( !pool_sessions.push( stc_ptr ) ){}
1792 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1793 boost::format fmt1("pool_session.size = %d");
1794 fmt1 % pool_sessions.size();
1795 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 92, fmt1.str(), __FILE__, __LINE__);
1796 boost::format fmt2("active_session.size = %d");
1797 fmt2 % active_sessions.size();
1798 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 93, fmt2.str(), __FILE__, __LINE__);
1799 boost::format fmt3("active_count = %d");
1800 fmt3 % active_count.get();
1801 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 94, fmt3.str(), __FILE__, __LINE__);
1803 boost::format funclog_fmt("out_function: void virtualservice_tcp::release_session( "
1804 "const tcp_session* session_ptr ): session_ptr = %d");
1805 funclog_fmt % session_ptr;
1806 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 95, funclog_fmt.str(), __FILE__, __LINE__);
1811 // set_socket_option
1813 void l7vs::virtualservice_tcp::set_socket_option()
1816 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1817 boost::format funclog_fmt("in_function: void virtualservice_tcp::et_socket_option");
1818 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 96, funclog_fmt.str(), __FILE__, __LINE__);
1821 // socket option check & set
1822 //! TCP_DEFER_ACCEPT (false:not set,true:set option)
1823 defer_accept_opt = false;
1824 //! TCP_DEFER_ACCEPT option value
1825 defer_accept_val = 0;
1826 //! TCP_NODELAY (false:not set,true:set option)
1827 set_sock_opt.nodelay_opt = false;
1828 //! TCP_NODELAY option value (false:off,true:on)
1829 set_sock_opt.nodelay_val = false;
1830 //! TCP_CORK (false:not set,true:set option)
1831 set_sock_opt.cork_opt = false;
1832 //! TCP_CORK option value (false:off,true:on)
1833 set_sock_opt.cork_val = false;
1834 //! TCP_QUICKACK (false:not set,true:set option)
1835 set_sock_opt.quickack_opt = false;
1836 //! TCP_QUICKACK option value (false:off,true:on)
1837 set_sock_opt.quickack_val = false;
1839 // set socket option
1840 if (element.socket_option_tcp_defer_accept != 0) {
1841 defer_accept_opt = true;
1842 if (element.socket_option_tcp_defer_accept == 1) {
1843 defer_accept_val = 1;
1847 if (element.socket_option_tcp_nodelay != 0) {
1848 set_sock_opt.nodelay_opt = true;
1849 if (element.socket_option_tcp_nodelay == 1) {
1850 set_sock_opt.nodelay_val = true;
1854 if (element.socket_option_tcp_cork != 0) {
1855 set_sock_opt.cork_opt = true;
1856 if (element.socket_option_tcp_cork == 1) {
1857 set_sock_opt.cork_val = true;
1861 if (element.socket_option_tcp_quickack != 0) {
1862 set_sock_opt.quickack_opt = true;
1863 if (element.socket_option_tcp_quickack == 1) {
1864 set_sock_opt.quickack_val = true;
1868 //----Debug log----------------------------------------------------------------------
1869 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1870 boost::format formatter("set_socket_option"
1871 " defer_accept_opt[%s]"
1872 " defer_accept_val[%d]"
1878 " quickack_val[%s]");
1880 % (defer_accept_opt ? "true" : "false")
1882 % (set_sock_opt.nodelay_opt ? "true" : "false")
1883 % (set_sock_opt.nodelay_val ? "true" : "false")
1884 % (set_sock_opt.cork_opt ? "true" : "false")
1885 % (set_sock_opt.cork_val ? "true" : "false")
1886 % (set_sock_opt.quickack_opt ? "true" : "false")
1887 % (set_sock_opt.quickack_val ? "true" : "false");
1888 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 97, formatter.str(), __FILE__, __LINE__);
1890 //----Debug log----------------------------------------------------------------------
1894 //! get private key file password (for callback function)
1895 //! @return password string
1896 std::string l7vs::virtualservice_tcp::get_ssl_password()
1898 //*-------- DEBUG LOG --------*/
1899 if (unlikely(LOG_LV_DEBUG ==
1900 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1901 std::stringstream buf;
1902 buf << "in_function: ";
1903 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password()";
1904 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 98, buf.str(),
1905 __FILE__, __LINE__);
1907 //*------ DEBUG LOG END ------*/
1909 // Get password from file.
1910 std::string retstr = "";
1912 char buf[MAX_SSL_PASSWD_SIZE + 3];
1913 if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1915 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1916 "Password file cannot open.", __FILE__, __LINE__);
1918 if (fgets(buf, MAX_SSL_PASSWD_SIZE + 3, fp) == NULL) {
1919 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
1920 "Password not found in file.",
1921 __FILE__, __LINE__);
1923 if (strlen(buf) > MAX_SSL_PASSWD_SIZE) {
1924 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1925 "Password is too long.",
1926 __FILE__, __LINE__);
1928 buf[strlen(buf) - 1] = '\0';
1935 //*-------- DEBUG LOG --------*/
1936 if (unlikely(LOG_LV_DEBUG ==
1937 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1938 std::stringstream buf;
1939 buf << "out_function: ";
1940 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password(): ";
1941 buf << "retstr = " << retstr;
1942 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 99, buf.str(),
1943 __FILE__, __LINE__);
1945 //*------ DEBUG LOG END ------*/
1951 //! Convert verify option string to integer(#define).
1953 //! @param[in] opt_string option string
1954 //! @retval ret option value
1955 //! @retval -1 no match
1956 int l7vs::virtualservice_tcp::conv_verify_option(std::string opt_string)
1958 //*-------- DEBUG LOG --------*/
1959 if (unlikely(LOG_LV_DEBUG ==
1960 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1961 std::stringstream buf;
1962 buf << "in_function: ";
1963 buf << "int virtualservice_tcp::conv_verify_option";
1964 buf << "(std::string opt_string): ";
1965 buf << "opt_string = " << opt_string;
1966 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 100, buf.str(),
1967 __FILE__, __LINE__);
1969 //*------ DEBUG LOG END ------*/
1973 // /usr/include/openssl/ssl.h
1974 // #define SSL_VERIFY_NONE 0x00
1975 // #define SSL_VERIFY_PEER 0x01
1976 // #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
1977 // #define SSL_VERIFY_CLIENT_ONCE 0x04
1979 if (opt_string == "SSL_VERIFY_NONE") {
1980 ret = SSL_VERIFY_NONE;
1981 } else if (opt_string == "SSL_VERIFY_PEER") {
1982 ret = SSL_VERIFY_PEER;
1983 } else if (opt_string == "SSL_VERIFY_FAIL_IF_NO_PEER_CERT") {
1984 ret = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1985 } else if (opt_string == "SSL_VERIFY_CLIENT_ONCE") {
1986 ret = SSL_VERIFY_CLIENT_ONCE;
1988 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
1989 "verify option string no match.",
1990 __FILE__, __LINE__);
1993 //*-------- DEBUG LOG --------*/
1994 if (unlikely(LOG_LV_DEBUG ==
1995 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1996 std::stringstream buf;
1997 buf << "out_function: ";
1998 buf << "int virtualservice_tcp::conv_verify_option";
1999 buf << "(std::string opt_string): ";
2000 buf << "return_value = " << ret;
2001 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 101, buf.str(),
2002 __FILE__, __LINE__);
2004 //*------ DEBUG LOG END ------*/
2005 // if ret == -1 then No match.
2010 // Convert SSL option string to integer(#define).
2012 // @param[in] opt_string option string
2013 // @retval ret option value
2014 // @retval -1 no match
2015 long int l7vs::virtualservice_tcp::conv_ssl_option(std::string opt_string)
2017 //*-------- DEBUG LOG --------*/
2018 if (unlikely(LOG_LV_DEBUG ==
2019 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2020 std::stringstream buf;
2021 buf << "in_function: ";
2022 buf << "long int virtualservice_tcp::conv_ssl_option";
2023 buf << "(std::string opt_string): ";
2024 buf << "opt_string = " << opt_string;
2025 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 102, buf.str(),
2026 __FILE__, __LINE__);
2028 //*------ DEBUG LOG END ------*/
2032 // /usr/include/openssl/ssl.h
2033 // #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
2034 // #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
2035 // #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
2036 // #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
2037 // #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
2038 // #define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L
2039 // #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
2040 // #define SSL_OP_TLS_D5_BUG 0x00000100L
2041 // #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
2042 // #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L
2043 // #define SSL_OP_ALL 0x00000FF7L
2044 // #define SSL_OP_NO_QUERY_MTU 0x00001000L
2045 // #define SSL_OP_COOKIE_EXCHANGE 0x00002000L
2046 // #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
2047 // #define SSL_OP_SINGLE_ECDH_USE 0x00080000L
2048 // #define SSL_OP_SINGLE_DH_USE 0x00100000L
2049 // #define SSL_OP_EPHEMERAL_RSA 0x00200000L
2050 // #define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
2051 // #define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
2052 // #define SSL_OP_NO_SSLv2 0x01000000L
2053 // #define SSL_OP_NO_SSLv3 0x02000000L
2054 // #define SSL_OP_NO_TLSv1 0x04000000L
2055 // #define SSL_OP_PKCS1_CHECK_1 0x08000000L
2056 // #define SSL_OP_PKCS1_CHECK_2 0x10000000L
2057 // #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
2058 // #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
2059 if (opt_string == "SSL_OP_MICROSOFT_SESS_ID_BUG") {
2060 ret = SSL_OP_MICROSOFT_SESS_ID_BUG;
2061 } else if (opt_string == "SSL_OP_NETSCAPE_CHALLENGE_BUG") {
2062 ret = SSL_OP_NETSCAPE_CHALLENGE_BUG;
2063 } else if (opt_string == "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG") {
2064 ret = SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
2065 } else if (opt_string == "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG") {
2066 ret = SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
2067 } else if (opt_string == "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER") {
2068 ret = SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
2069 } else if (opt_string == "SSL_OP_MSIE_SSLV2_RSA_PADDING") {
2070 ret = SSL_OP_MSIE_SSLV2_RSA_PADDING;
2071 } else if (opt_string == "SSL_OP_SSLEAY_080_CLIENT_DH_BUG") {
2072 ret = SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
2073 } else if (opt_string == "SSL_OP_TLS_D5_BUG") {
2074 ret = SSL_OP_TLS_D5_BUG;
2075 } else if (opt_string == "SSL_OP_TLS_BLOCK_PADDING_BUG") {
2076 ret = SSL_OP_TLS_BLOCK_PADDING_BUG;
2077 } else if (opt_string == "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS") {
2078 ret = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
2079 } else if (opt_string == "SSL_OP_ALL") {
2080 // boost::asio::ssl::context::default_workarounds
2082 } else if (opt_string == "SSL_OP_NO_QUERY_MTU") {
2083 ret = SSL_OP_NO_QUERY_MTU;
2084 } else if (opt_string == "SSL_OP_COOKIE_EXCHANGE") {
2085 ret = SSL_OP_COOKIE_EXCHANGE;
2086 } else if (opt_string == "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION") {
2087 ret = SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
2088 } else if (opt_string == "SSL_OP_SINGLE_ECDH_USE") {
2089 ret = SSL_OP_SINGLE_ECDH_USE;
2090 } else if (opt_string == "SSL_OP_SINGLE_DH_USE") {
2091 // boost::asio::ssl::context::single_dh_use
2092 ret = SSL_OP_SINGLE_DH_USE;
2093 } else if (opt_string == "SSL_OP_EPHEMERAL_RSA") {
2094 ret = SSL_OP_EPHEMERAL_RSA;
2095 } else if (opt_string == "SSL_OP_CIPHER_SERVER_PREFERENCE") {
2096 ret = SSL_OP_CIPHER_SERVER_PREFERENCE;
2097 } else if (opt_string == "SSL_OP_TLS_ROLLBACK_BUG") {
2098 ret = SSL_OP_TLS_ROLLBACK_BUG;
2099 } else if (opt_string == "SSL_OP_NO_SSLv2") {
2100 // boost::asio::ssl::context::no_sslv2
2101 ret = SSL_OP_NO_SSLv2;
2102 } else if (opt_string == "SSL_OP_NO_SSLv3") {
2103 // boost::asio::ssl::context::no_sslv3
2104 ret = SSL_OP_NO_SSLv3;
2105 } else if (opt_string == "SSL_OP_NO_TLSv1") {
2106 // boost::asio::ssl::context::no_tlsv1
2107 ret = SSL_OP_NO_TLSv1;
2108 } else if (opt_string == "SSL_OP_PKCS1_CHECK_1") {
2109 ret = SSL_OP_PKCS1_CHECK_1;
2110 } else if (opt_string == "SSL_OP_PKCS1_CHECK_2") {
2111 ret = SSL_OP_PKCS1_CHECK_2;
2112 } else if (opt_string == "SSL_OP_NETSCAPE_CA_DN_BUG") {
2113 ret = SSL_OP_NETSCAPE_CA_DN_BUG;
2114 } else if (opt_string == "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG") {
2115 ret = SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
2117 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
2118 "ssl option string no match.",
2119 __FILE__, __LINE__);
2122 //*-------- DEBUG LOG --------*/
2123 if (unlikely(LOG_LV_DEBUG ==
2124 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2125 std::stringstream buf;
2126 buf << "out_function: ";
2127 buf << "long int virtualservice_tcp::conv_ssl_option";
2128 buf << "(std::string opt_string): ";
2129 buf << "return_value = " << ret;
2130 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 103, buf.str(),
2131 __FILE__, __LINE__);
2133 //------ DEBUG LOG END ------*/
2134 // if ret == -1 then No match.
2139 //! get ssl parameter
2140 //! @return get ssl parameter result
2141 bool l7vs::virtualservice_tcp::get_ssl_parameter()
2143 //*-------- DEBUG LOG --------*/
2144 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2145 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 104,
2146 "in_function: bool virtualservice_tcp::get_ssl_parameter()",
2147 __FILE__, __LINE__);
2149 //*------ DEBUG LOG END ------*/
2150 typedef std::vector< std::string > string_vector_type;
2153 string_vector_type string_vector;
2154 l7vs::error_code err;
2155 bool retbool = false;
2158 // param init ( ssl configuration file )
2159 if (unlikely(!param.init(l7vs::PARAM_COMP_SSL, ssl_file_name))) {
2160 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 24,
2161 "SSL config file read error.",
2162 __FILE__, __LINE__);
2166 //// SSL context parameter
2167 // Get parameter "ca_dir".
2168 ca_dir = param.get_string(l7vs::PARAM_COMP_SSL, "ca_dir",
2169 err, ssl_file_name);
2170 if (unlikely(err) || ca_dir == "") {
2171 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 9,
2172 "ca_dir parameter not found. Use default value.",
2173 __FILE__, __LINE__);
2174 ca_dir = DEFAULT_SSL_CA_DIR;
2177 // Get parameter "ca_file".
2178 ca_file = param.get_string(l7vs::PARAM_COMP_SSL, "ca_file",
2179 err, ssl_file_name);
2180 if (unlikely(err)) {
2181 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 25,
2182 "Cannot get ca_file parameter.",
2183 __FILE__, __LINE__);
2187 // Get parameter "cert_chain_dir".
2188 cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2192 if (unlikely(err) || cert_chain_dir == "") {
2193 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 10,
2194 "cert_chain_dir parameter not found. Use default value.",
2195 __FILE__, __LINE__);
2196 cert_chain_dir = DEFAULT_SSL_CERT_CHAIN_DIR;
2199 // Get parameter "cert_chain_file".
2200 cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
2204 if (unlikely(err) || cert_chain_file == "") {
2205 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 26,
2206 "Cannot get cert_chain_file parameter.",
2207 __FILE__, __LINE__);
2211 // Get parameter "private_key_dir".
2212 private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2216 if (unlikely(err) || private_key_dir == "") {
2217 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 11,
2218 "private_key_dir parameter not found. Use default value.",
2219 __FILE__, __LINE__);
2220 private_key_dir = DEFAULT_SSL_PRIVATE_KEY_DIR;
2223 // Get parameter "private_key_file".
2224 private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
2228 if (unlikely(err) || private_key_file == "") {
2229 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 27,
2230 "Cannot get private_key_file parameter.",
2231 __FILE__, __LINE__);
2235 // Get parameter "private_key_filetype".
2236 // and convert string to filetype define value.
2238 // /usr/include/openssl/ssl.h
2239 // #define SSL_FILETYPE_PEM X509_FILETYPE_PEM ->1
2240 // #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 ->2
2241 std::string filetype_str = param.get_string(
2242 l7vs::PARAM_COMP_SSL,
2243 "private_key_filetype",
2246 if (unlikely(err) || filetype_str == "") {
2247 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 12,
2248 "private_key_filetype parameter not found. Use default value.",
2249 __FILE__, __LINE__);
2250 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
2251 } else if (filetype_str == "SSL_FILETYPE_PEM") {
2252 private_key_filetype = boost::asio::ssl::context::pem;
2253 } else if (filetype_str == "SSL_FILETYPE_ASN1") {
2254 private_key_filetype = boost::asio::ssl::context::asn1;
2256 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
2257 "private_key_filetype convert error.",
2258 __FILE__, __LINE__);
2262 // Get parameter "private_key_passwd_dir".
2263 private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2264 "private_key_passwd_dir",
2267 if (unlikely(err) || private_key_passwd_dir == "") {
2268 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 13,
2269 "private_key_passwd_dir parameter not found. Use default value.",
2270 __FILE__, __LINE__);
2271 private_key_passwd_dir = DEFAULT_SSL_PRIVATE_KEY_PASSWD_DIR;
2274 // Get parameter "private_key_passwd_file".
2275 private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2276 "private_key_passwd_file",
2279 if (unlikely(err) || private_key_passwd_file == "") {
2280 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
2281 "Cannot get private_key_passwd_file parameter.",
2282 __FILE__, __LINE__);
2286 // Get parameter "verify_options".
2287 param.get_multistring(l7vs::PARAM_COMP_SSL,
2292 if (unlikely(err)) {
2293 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 14,
2294 "verify_options parameter not found. Use default value.",
2295 __FILE__, __LINE__);
2296 verify_options = DEFAULT_SSL_VERIFY_OPTIONS;
2298 // Make verify option bit data.
2299 for (string_vector_type::iterator itr = string_vector.begin();
2300 itr != string_vector.end(); ++itr) {
2301 // Convert string to define value.
2302 int int_val = conv_verify_option(*itr);
2303 if (unlikely(int_val == -1)) {
2304 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 30,
2305 "verify_options convert error.",
2306 __FILE__, __LINE__);
2309 verify_options = (verify_options | int_val);
2313 // Get parameter "verify_cert_depth".
2314 verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2315 "verify_cert_depth",
2318 if (unlikely(err)) {
2319 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 15,
2320 "verify_cert_depth parameter not found. Use default value.",
2321 __FILE__, __LINE__);
2322 verify_cert_depth = DEFAULT_SSL_VERIFY_CERT_DEPTH;
2323 } else if (unlikely(verify_cert_depth < 0 ||
2324 verify_cert_depth > INT_MAX)) {
2325 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 31,
2326 "Invalid verify_cert_depth parameter value.",
2327 __FILE__, __LINE__);
2331 // Get parameter "ssl_options".
2332 // and Check dh parameter file use or not.
2333 is_tmp_dh_use = false;
2334 param.get_multistring(l7vs::PARAM_COMP_SSL,
2339 if (unlikely(err)) {
2340 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 16,
2341 "ssl_options parameter not found. Use default value.",
2342 __FILE__, __LINE__);
2343 ssl_options = DEFAULT_SSL_OPTIONS;
2344 is_tmp_dh_use = true;
2346 // Make ssl option bit data.
2347 for (string_vector_type::iterator itr = string_vector.begin();
2348 itr != string_vector.end(); ++itr) {
2349 // Convert string to define value.
2350 long int longint_val = conv_ssl_option(*itr);
2351 if (unlikely(longint_val == -1)) {
2352 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 32,
2353 "ssl_options convert error.",
2354 __FILE__, __LINE__);
2356 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2357 is_tmp_dh_use = true;
2359 ssl_options = (ssl_options | longint_val);
2363 if (is_tmp_dh_use) {
2364 // Get parameter "tmp_dh_dir".
2365 tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2369 if (unlikely(err) || tmp_dh_dir == "") {
2370 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
2371 "tmp_dh_dir parameter not found. Use default value.",
2372 __FILE__, __LINE__);
2373 tmp_dh_dir = DEFAULT_SSL_TMP_DH_DIR;
2375 // Get parameter "tmp_dh_file".
2376 tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2380 if (unlikely(err) || tmp_dh_file == "") {
2381 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 33,
2382 "Cannot get tmp_dh_file parameter.",
2383 __FILE__, __LINE__);
2388 // Get parameter "cipher_list".
2389 cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2393 if (unlikely(err) || cipher_list == "") {
2394 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 18,
2395 "cipher_list parameter not found. Use default value.",
2396 __FILE__, __LINE__);
2397 cipher_list = DEFAULT_SSL_CIPHER_LIST;
2400 //// SSL session cache parameter
2401 // Get parameter "session_cache".
2402 is_session_cache_use = false;
2403 std::string cache_str = param.get_string(l7vs::PARAM_COMP_SSL,
2407 if (unlikely(err) || cache_str == "") {
2408 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
2409 "session_cache parameter not found. Use default value.",
2410 __FILE__, __LINE__);
2411 is_session_cache_use = true;
2412 } else if (cache_str == "on") {
2413 is_session_cache_use = true;
2414 } else if (cache_str == "off") {
2415 is_session_cache_use = false;
2417 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2418 "Invalid session_cache parameter value.", __FILE__, __LINE__);
2422 if (is_session_cache_use) {
2423 session_cache_mode = DEFAULT_SSL_SESSION_CACHE_MODE;
2424 // Get parameter "session_cache_size".
2425 session_cache_size = param.get_int(l7vs::PARAM_COMP_SSL,
2426 "session_cache_size",
2429 if (unlikely(err)) {
2430 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
2431 "session_cache_size parameter not found. Use default value.",
2432 __FILE__, __LINE__);
2433 session_cache_size = DEFAULT_SSL_SESSION_CACHE_SIZE;
2434 } else if (session_cache_size < 0 ||
2435 session_cache_size > INT_MAX) {
2436 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 35,
2437 "Invalid session_cache_size parameter value.", __FILE__, __LINE__);
2440 // Get parameter "session_cache_timeout".
2441 session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2442 "session_cache_timeout",
2445 if (unlikely(err)) {
2446 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
2447 "session_cache_timeout parameter not found. Use default value.",
2448 __FILE__, __LINE__);
2449 session_cache_timeout = DEFAULT_SSL_SESSION_CACHE_TIMEOUT;
2450 } else if (session_cache_timeout < 0 ||
2451 session_cache_timeout > INT_MAX) {
2452 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 36,
2453 "Invalid session_cache_timeout parameter value.",
2454 __FILE__, __LINE__);
2458 session_cache_mode = SSL_SESS_CACHE_OFF;
2461 //// SSL handshake timer parameter
2462 // Get parameter "timeout_sec".
2463 handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2467 if (unlikely(err)) {
2468 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2469 "timeout_sec parameter not found. Use default value.", __FILE__, __LINE__);
2470 handshake_timeout = DEFAULT_SSL_HANDSHAKE_TIMEOUT;
2471 } else if (handshake_timeout <= 0 || handshake_timeout > INT_MAX) {
2472 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 37,
2473 "Invalid timeout_sec parameter value.", __FILE__, __LINE__);
2483 //*-------- DEBUG LOG --------*/
2484 if (unlikely(LOG_LV_DEBUG ==
2485 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2486 std::stringstream buf;
2487 buf << "out_function: bool virtualservice_tcp::get_ssl_parameter(): ";
2488 buf << "ca_dir = " << ca_dir << ", ";
2489 buf << "ca_file = " << ca_file << ", ";
2490 buf << "cert_chain_dir = " << cert_chain_dir << ", ";
2491 buf << "cert_chain_file = " << cert_chain_file << ", ";
2492 buf << "private_key_dir = " << private_key_dir << ", ";
2493 buf << "private_key_file = " << private_key_file << ", ";
2494 buf << "private_key_filetype = " << private_key_filetype << ", ";
2495 buf << "private_key_passwd_dir = " << private_key_passwd_dir << ", ";
2496 buf << "private_key_passwd_file = " << private_key_passwd_file << ", ";
2497 buf << "verify_options = " << verify_options << ", ";
2498 buf << "verify_cert_depth = " << verify_cert_depth << ", ";
2499 buf << "ssl_options = " << ssl_options << ", ";
2500 if (is_tmp_dh_use) {
2501 buf << "tmp_dh_dir = " << tmp_dh_dir << ", ";
2502 buf << "tmp_dh_file = " << tmp_dh_file << ", ";
2504 buf << "cipher_list = " << cipher_list << ", ";
2505 buf << "session_cache_mode = " << session_cache_mode << ", ";
2506 if (is_session_cache_use) {
2507 buf << "session_cache_size = " << session_cache_size << ", ";
2508 buf << "session_cache_timeout = " << session_cache_timeout << ", ";
2510 buf << "handshake_timeout = " << handshake_timeout;
2511 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2513 __FILE__, __LINE__);
2515 //*------ DEBUG LOG END ------*/
2520 // set ssl context and ssl session cache configuration
2521 // @return set ssl config result
2522 bool l7vs::virtualservice_tcp::set_ssl_config()
2524 //*-------- DEBUG LOG --------*/
2525 if (unlikely(LOG_LV_DEBUG ==
2526 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2527 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 106,
2528 "in_function: bool virtualservice_tcp::set_ssl_config()",
2529 __FILE__, __LINE__);
2531 //*------ DEBUG LOG END ------*/
2533 bool retbool = false;
2536 //// SSL context setting.
2538 if (ca_file.size() == 0) {
2539 // specified CA path.
2541 sslcontext->add_verify_path(ca_dir);
2542 } catch (std::exception &e) {
2543 std::stringstream buf;
2544 buf << "Set root CA path error: " << e.what() << ".";
2545 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2547 __FILE__, __LINE__);
2551 // specified CA file.
2553 sslcontext->load_verify_file(ca_dir + ca_file);
2554 } catch (std::exception &e) {
2555 std::stringstream buf;
2556 buf << "Set root CA file error: " << e.what() << ".";
2557 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2559 __FILE__, __LINE__);
2564 // Set certificate chain file.
2566 sslcontext->use_certificate_chain_file(
2567 cert_chain_dir + cert_chain_file);
2568 } catch (std::exception &e) {
2569 std::stringstream buf;
2570 buf << "Set certificate chain file error: " << e.what() << ".";
2571 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2572 __FILE__, __LINE__);
2576 // Set password callback function.
2578 sslcontext->set_password_callback(
2579 boost::bind(&virtualservice_tcp::get_ssl_password, this));
2580 } catch (std::exception &e) {
2581 std::stringstream buf;
2582 buf << "Set password callback error: " << e.what() << ".";
2583 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2584 __FILE__, __LINE__);
2588 // Set private key file and filetype.
2590 sslcontext->use_private_key_file(
2591 private_key_dir + private_key_file, private_key_filetype);
2592 } catch (std::exception &e) {
2593 std::stringstream buf;
2594 buf << "Set private key file and filetype error: " << e.what() << ".";
2595 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2596 __FILE__, __LINE__);
2600 // Set verify options on the context.
2602 sslcontext->set_verify_mode(verify_options);
2603 } catch (std::exception &e) {
2604 std::stringstream buf;
2605 buf << "Set verify option error: " << e.what() << ".";
2606 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2607 __FILE__, __LINE__);
2611 // Set verify depth on the context.
2612 SSL_CTX_set_verify_depth(sslcontext->impl(), verify_cert_depth);
2614 // Set SSL options on the context.
2616 sslcontext->set_options(ssl_options);
2617 } catch (std::exception &e) {
2618 std::stringstream buf;
2619 buf << "Set SSL option error: " << e.what() << ".";
2620 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2621 __FILE__, __LINE__);
2625 // Set temporary Diffie-Hellman parameters file.
2626 if (is_tmp_dh_use) {
2628 sslcontext->use_tmp_dh_file(tmp_dh_dir + tmp_dh_file);
2629 } catch (std::exception &e) {
2630 std::stringstream buf;
2631 buf << "Set tmp DH file error: " << e.what() << ".";
2632 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2634 __FILE__, __LINE__);
2640 // Set cipher list on the context.
2641 if (unlikely(SSL_CTX_set_cipher_list(sslcontext->impl(),
2642 cipher_list.c_str()) != 1)) {
2643 std::stringstream buf;
2644 buf << "Set cipher list error.";
2645 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2647 __FILE__, __LINE__);
2651 //// SSL session cache setting.
2652 if (is_session_cache_use) {
2653 // Set session id context on the context.
2654 if (unlikely(SSL_CTX_set_session_id_context(
2656 (const unsigned char *)"ultramonkey", 11) != 1)) {
2657 std::stringstream buf;
2658 buf << "Set session id context error.";
2659 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2661 __FILE__, __LINE__);
2665 // Set session cache mode on the context.
2666 SSL_CTX_set_session_cache_mode(
2667 sslcontext->impl(), session_cache_mode);
2669 // Set session cache size on the context.
2670 SSL_CTX_sess_set_cache_size(sslcontext->impl(), session_cache_size);
2672 // Set session cache timeout on the context.
2673 SSL_CTX_set_timeout(sslcontext->impl(), session_cache_timeout);
2676 // session cache OFF.
2677 SSL_CTX_set_session_cache_mode(sslcontext->impl(),
2678 SSL_SESS_CACHE_OFF);
2686 //*-------- DEBUG LOG --------*/
2687 if (unlikely(LOG_LV_DEBUG ==
2688 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2689 std::stringstream buf;
2690 buf << "out_function: bool virtualservice_tcp::set_ssl_config(): ";
2691 get_ssl_config(buf);
2692 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 117, buf.str(),
2693 __FILE__, __LINE__);
2695 //*------ DEBUG LOG END ------*/
2700 // flush ssl session
2701 void l7vs::virtualservice_tcp::flush_ssl_session()
2703 // check expired cached sessions and do flushing
2704 // Need ssl_context lock?
2705 SSL_CTX_flush_sessions(sslcontext->impl(), time(0));
2709 // get ssl configuration form ssl context. (for debug)
2710 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream &buf)
2712 buf << "SSL configuration information: ";
2713 buf << "Verify mode[" << SSL_CTX_get_verify_mode(sslcontext->impl()) << "] ";
2714 buf << "Verify depth[" << SSL_CTX_get_verify_depth(sslcontext->impl()) << "] ";
2715 buf << "SSL options[" << SSL_CTX_get_options(sslcontext->impl()) << "] ";
2716 buf << "Cache mode[" << SSL_CTX_get_session_cache_mode(sslcontext->impl()) << "] ";
2717 buf << "Cache size[" << SSL_CTX_sess_get_cache_size(sslcontext->impl()) << "] ";
2718 buf << "Cache timeout[" << SSL_CTX_get_timeout(sslcontext->impl()) << "] ";
2722 // get ssl session cache information form ssl context. (for debug)
2723 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream &buf)
2725 buf << "SSL session cache information: ";
2726 buf << "Session number[" << SSL_CTX_sess_number(sslcontext->impl()) << "] ";
2727 buf << "Accept[" << SSL_CTX_sess_accept(sslcontext->impl()) << "] ";
2728 buf << "Accept good[" << SSL_CTX_sess_accept_good(sslcontext->impl()) << "] ";
2729 buf << "Accept renegotiate[" << SSL_CTX_sess_accept_renegotiate(sslcontext->impl()) << "] ";
2730 buf << "Hits[" << SSL_CTX_sess_hits(sslcontext->impl()) << "] ";
2731 buf << "Misses[" << SSL_CTX_sess_misses(sslcontext->impl()) << "] ";
2732 buf << "Timeouts[" << SSL_CTX_sess_timeouts(sslcontext->impl()) << "] ";
2733 buf << "Cache full[" << SSL_CTX_sess_cache_full(sslcontext->impl()) << "] ";