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>
33 #include "virtualservice.h"
34 #include "logger_enum.h"
36 #include "parameter.h"
37 #include "snmpagent.h"
39 #include "logger_access_manager.h"
41 // implementation for virtualservice_tcp
43 * virtualservice_tcp class constructor.
45 l7vs::virtualservice_tcp::virtualservice_tcp(const l7vsd &invsd,
46 const replication &inrep,
47 const virtualservice_element &inelement)
49 virtualservice_base(invsd, inrep, inelement),
50 acceptor_(dispatcher),
51 sslcontext(dispatcher, DEFAULT_SSL_METHOD),
52 access_log_file_name("")
60 private_key_file = "";
61 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
62 private_key_passwd_dir = "";
63 private_key_passwd_file = "";
65 verify_cert_depth = 0;
67 is_tmp_dh_use = false;
71 is_session_cache_use = false;
72 session_cache_mode = 0;
73 session_cache_size = 0;
74 session_cache_timeout = 0;
75 handshake_timeout = 0;
78 * virtualservice_tcp class destructor.
80 l7vs::virtualservice_tcp::~virtualservice_tcp()
84 * replication interrupt event
89 void l7vs::virtualservice_tcp::handle_replication_interrupt(const boost::system::error_code &err)
91 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
92 boost::format fmt("in_function: void virtualservice_tcp::handle_replication_interrupt( "
93 "const boost::system::error_code& err ): err = %s, err.message = %s");
94 fmt % (err ? "true" : "false") % err.message();
95 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 20, fmt.str(), __FILE__, __LINE__);
100 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, err.message(), __FILE__, __LINE__);
104 interrupt_running_flag++;
107 replication &rep_noconst = const_cast<replication &>(rep);
109 if (replication::REPLICATION_SINGLE == rep_noconst.get_status()) {
110 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "replication mode is single.",
112 interrupt_running_flag--;
116 std::stringstream tmp_tcp_ep;
117 tmp_tcp_ep << element.tcp_accept_endpoint;
118 std::stringstream tmp_udp_ep;
119 tmp_udp_ep << element.udp_recv_endpoint;
120 std::stringstream tmp_sorry_ep;
121 tmp_sorry_ep << element.sorry_endpoint;
123 //get replication area
124 unsigned int rep_size = 0;
125 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
126 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
127 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
128 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 1, REP_BLOCK_SIZE_ERR_MSG,
130 interrupt_running_flag--;
134 //check max data size
135 if ((rep_size * DATA_SIZE) <
136 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
137 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, REP_AREA_SIZE_ERR_MSG,
139 interrupt_running_flag--;
143 //lock replication area
144 rep_noconst.lock(REP_AREA_NAME);
146 //read header value and set loop count
147 unsigned int loop_cnt = rep_header_ptr->data_num;
148 //if data_num over MAX_REPLICATION_DATA_NUM, data_num = 0
149 if (static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt) {
153 //set start pointer(pointer of replication_data)
154 replication_data *rep_data_ptr = reinterpret_cast<replication_data *>(++rep_header_ptr);
157 for (unsigned int i = 0; i < loop_cnt; ++i) {
158 //check equal udpmode and tcp_accept_endpoint
159 if ((rep_data_ptr->udpmode == element.udpmode) &&
160 (0 == strncmp(rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 47))) {
164 //increment data pointer
168 //if it is new data, increment data num.
170 rep_header_ptr = reinterpret_cast<replication_header *>(
171 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
172 ++(rep_header_ptr->data_num);
174 //write replication data
175 rep_data_ptr->udpmode = element.udpmode;
176 strncpy(rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 48);
177 strncpy(rep_data_ptr->udp_endpoint, tmp_udp_ep.str().c_str(), 48);
178 rep_data_ptr->sorry_maxconnection = element.sorry_maxconnection;
179 strncpy(rep_data_ptr->sorry_endpoint, tmp_sorry_ep.str().c_str(), 48);
180 rep_data_ptr->sorry_flag = element.sorry_flag;
181 rep_data_ptr->sorry_fwdmode = element.sorry_fwdmode;
182 rep_data_ptr->qos_up = element.qos_upstream;
183 rep_data_ptr->qos_down = element.qos_downstream;
185 //unlock replication area
186 rep_noconst.unlock(REP_AREA_NAME);
188 if (0 == virtualservice_stop_flag.get()) {
189 //register handle_replication_interrupt
190 replication_timer->expires_from_now(
191 boost::posix_time::milliseconds(param_data.rep_interval));
192 replication_timer->async_wait(boost::bind(
193 &virtualservice_tcp::handle_replication_interrupt,
194 this, boost::asio::placeholders::error));
196 interrupt_running_flag--;
198 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
199 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
200 "out_function: void virtualservice_tcp::handle_replication_interrupt( "
201 "const boost::system::error_code& err )", __FILE__, __LINE__);
206 * read replication data
208 * @param read_replicationdata
212 void l7vs::virtualservice_tcp::read_replicationdata()
214 Logger funclog(LOG_CAT_L7VSD_VIRTUALSERVICE, 22, "function: "
215 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
217 replication &rep_noconst = const_cast<replication &>(rep);
219 if (replication::REPLICATION_SINGLE == rep_noconst.get_status()) {
220 Logger::putLogInfo(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, "replication mode is single.",
225 unsigned int rep_size = 0;
226 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
227 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
228 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
229 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 3, REP_BLOCK_SIZE_ERR_MSG,
231 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
232 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 23, "out_function: "
233 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
238 //check max data size
239 if ((rep_size * DATA_SIZE) <
240 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
241 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 4, REP_AREA_SIZE_ERR_MSG,
243 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
244 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 24, "out_function: "
245 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
249 //lock replication area
250 rep_noconst.lock(REP_AREA_NAME);
252 //read header value and set loop count
253 unsigned int loop_cnt = rep_header_ptr->data_num;
254 //if data_num over MAX_REPLICATION_DATA_NUM, set data_num = 0
255 if (static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt) {
256 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 5, REP_BLOCK_SIZE_ERR_MSG,
258 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
259 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 25, "out_function: "
260 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
262 rep_header_ptr->data_num = 0;
263 rep_noconst.unlock(REP_AREA_NAME);
267 //set start pointer(pointer of replication_data)
268 replication_data *rep_data_ptr = reinterpret_cast<replication_data *>(++rep_header_ptr);
271 for (unsigned int i = 0; i < loop_cnt; ++i) {
272 //get tcp endpoint data
273 std::string tmpstr = rep_data_ptr->tcp_endpoint;
275 unsigned short portno;
277 portno = boost::lexical_cast<unsigned short>(tmpstr.substr((tmpstr.rfind(":") + 1)));
278 } catch (const boost::bad_lexical_cast &err) {
281 if (tmpstr[0] == '[') {
283 ipaddr = tmpstr.substr(1, (tmpstr.rfind("]") - 1));
286 ipaddr = tmpstr.substr(0, tmpstr.rfind(":"));
288 //check equal udpmode and tcp_accept_endpoint
289 if ((rep_data_ptr->udpmode == element.udpmode) &&
290 (tcp_endpoint_type(boost::asio::ip::address::from_string(ipaddr), portno)
291 == element.tcp_accept_endpoint)) {
292 element.sorry_maxconnection = rep_data_ptr->sorry_maxconnection;
293 tmpstr = rep_data_ptr->sorry_endpoint;
295 portno = boost::lexical_cast<unsigned short>(
296 tmpstr.substr((tmpstr.rfind(":") + 1)));
297 } catch (const boost::bad_lexical_cast &err) {
300 if (tmpstr[0] == '[') {
302 ipaddr = tmpstr.substr(1, (tmpstr.rfind("]") - 1));
305 ipaddr = tmpstr.substr(0, tmpstr.rfind(":"));
307 element.sorry_endpoint =
308 tcp_endpoint_type(boost::asio::ip::address::from_string(ipaddr), portno);
309 element.sorry_flag = rep_data_ptr->sorry_flag;
310 element.sorry_fwdmode = (virtualservice_element::SORRYSERVER_FWDMODE_TAG)(rep_data_ptr->sorry_fwdmode);
311 element.qos_upstream = rep_data_ptr->qos_up;
312 element.qos_downstream = rep_data_ptr->qos_down;
315 //increment data pointer
319 //unlock replication area
320 rep_noconst.unlock(REP_AREA_NAME);
322 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
323 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 26, "out_function: "
324 "void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__);
331 * @param handle_accept
335 void l7vs::virtualservice_tcp::handle_accept(const l7vs::session_thread_control *stc_ptr, const boost::system::error_code &err)
337 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
338 boost::format funclog_fmt("in_function: void virtualservice_tcp::handle_accept( "
339 "const boost::shared_ptr<session_thread_control> , "
340 "const boost::system::error_code& err ): err = %s, err.message = %s");
341 funclog_fmt % (err ? "true" : "false") % err.message();
342 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 27, funclog_fmt.str(), __FILE__, __LINE__);
345 session_thread_control *stc_ptr_noconst = const_cast<session_thread_control *>(stc_ptr);
349 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 2, err.message(), __FILE__, __LINE__);
353 tcp_session *tmp_session = stc_ptr_noconst->get_session().get();
355 if (ssl_file_name != "") {
357 //*-------- DEBUG LOG --------*/
358 if (unlikely(LOG_LV_DEBUG ==
359 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
360 std::stringstream buf;
361 buf << "virtualservice_tcp::handle_accept(): ";
362 buf << "ssl session cache flush before: ";
363 get_ssl_session_cache_info(buf);
364 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
368 //*------ DEBUG LOG END ------*/
370 // ssl session cache flush
371 if (is_session_cache_use == true) {
372 long ssl_cache_num = SSL_CTX_sess_number(sslcontext.impl());
373 if (ssl_cache_num >= session_cache_size) {
378 //*-------- DEBUG LOG --------*/
379 if (unlikely(LOG_LV_DEBUG ==
380 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
381 std::stringstream buf;
382 buf << "virtualservice_tcp::handle_accept(): ";
383 buf << "ssl session cache flush after: ";
384 get_ssl_session_cache_info(buf);
385 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
389 //*------ DEBUG LOG END ------*/
392 // send access log output ON or OFF message to tcp_session
393 stc_ptr_noconst->session_access_log_output_mode_change(access_log_flag);
395 active_sessions.insert(tmp_session, stc_ptr_noconst);
397 //check sorry flag and status
398 if (unlikely((0 != element.sorry_flag) ||
399 ((0 < element.sorry_maxconnection) &&
400 ((active_count.get() >= static_cast<size_t>(element.sorry_maxconnection)))))) {
401 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
402 boost::format fmt("Connection switch Sorry mode. "
403 "active_session.size = %d, active_count.get = %d");
404 fmt % active_sessions.size() % active_count.get();
405 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 30, fmt.str(), __FILE__, __LINE__);
407 stc_ptr_noconst->get_session()->set_virtual_service_message(tcp_session::SORRY_STATE_ENABLE);
410 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
411 boost::format fmt1("active session thread id = %d");
412 fmt1 % stc_ptr_noconst->get_upthread_id();
413 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 31, fmt1.str(), __FILE__, __LINE__);
414 boost::format fmt2("pool_session.size = %d");
415 fmt2 % pool_sessions.size();
416 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 32, fmt2.str(), __FILE__, __LINE__);
417 boost::format fmt3("active_session.size = %d");
418 fmt3 % active_sessions.size();
419 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 33, fmt3.str(), __FILE__, __LINE__);
420 boost::format fmt4("active_count = %d");
421 fmt4 % active_count.get();
422 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 34, fmt4.str(), __FILE__, __LINE__);
425 session_thread_control *tmp_stc_ptr = waiting_sessions.find(stc_ptr_noconst->get_session().get());
426 waiting_sessions.erase(tmp_stc_ptr->get_session().get());
428 stc_ptr_noconst->startupstream();
429 stc_ptr_noconst->startdownstream();
431 //left session is less than the threshold
432 if ((sessionpool_alert_flag == false) &&
433 ((pool_sessions.size() + waiting_sessions.size()) < param_data.session_pool_alert_on)) {
434 //create trap message
435 trapmessage trap_msg;
436 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
437 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
439 //push the trap message
440 snmpagent::push_trapmessage(trap_msg, err_code);
442 std::string msg("Push trap message failed.");
443 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 38, msg, __FILE__, __LINE__);
445 //set sessionpool alert flag true
446 sessionpool_alert_flag = true;
449 //waiting, pool_sessions.size become over 1
450 //pick up session from pool
451 session_thread_control *stc_ptr_register_accept;
452 stc_ptr_register_accept = pool_sessions.pop();
453 while (unlikely(!stc_ptr_register_accept)) {
454 boost::this_thread::yield();
455 stc_ptr_register_accept = pool_sessions.pop();
458 //session add wait_sessions
459 boost::mutex::scoped_lock up_wait_lk(stc_ptr_register_accept->get_upthread_mutex());
460 boost::mutex::scoped_lock down_wait_lk(stc_ptr_register_accept->get_downthread_mutex());
462 waiting_sessions.insert(stc_ptr_register_accept->get_session().get(), stc_ptr_register_accept);
464 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
465 boost::format fmt1("active session thread id = %d");
466 fmt1 % stc_ptr_register_accept->get_upthread_id();
467 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 35, fmt1.str(), __FILE__, __LINE__);
468 boost::format fmt2("pool_session.size = %d");
469 fmt2 % pool_sessions.size();
470 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 36, fmt2.str(), __FILE__, __LINE__);
471 boost::format fmt3("active_session.size = %d");
472 fmt3 % active_sessions.size();
473 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 37, fmt3.str(), __FILE__, __LINE__);
474 boost::format fmt4("active_count = %d");
475 fmt4 % active_count.get();
476 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 38, fmt4.str(), __FILE__, __LINE__);
479 //register accept event handler
480 if (!ssl_virtualservice_mode_flag) {
481 acceptor_.async_accept(stc_ptr_register_accept->get_session()->get_client_socket(),
482 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr_register_accept,
483 boost::asio::placeholders::error));
485 acceptor_.async_accept(stc_ptr_register_accept->get_session()->get_client_ssl_socket().lowest_layer(),
486 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr_register_accept,
487 boost::asio::placeholders::error));
490 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
491 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 39, "out_function: "
492 "void virtualservice_tcp::handle_accept( "
493 "const boost::shared_ptr<session_thread_control> , "
494 "const boost::system::error_code& err )", __FILE__, __LINE__);
499 * initialize virtualservice(TCP)
504 void l7vs::virtualservice_tcp::initialize(l7vs::error_code &err)
506 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
507 boost::format formatter("in_function: void virtualservice_tcp::initialize( "
508 "l7vs::error_code& err )");
509 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, formatter.str(), __FILE__, __LINE__);
511 if (pool_sessions.size() != 0) {
512 err.setter(true, "VirtualService already initialized.");
513 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
514 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
515 "l7vs::error_code& err ): err = %s, err.message = %s");
516 formatter % (err ? "true" : "false") % err.get_message();
517 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 41, formatter.str(),
523 //load parameter value
526 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
527 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
528 "l7vs::error_code& err ): err = %s, err.message = %s");
529 formatter % (err ? "true" : "false") % err.get_message();
530 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 42, formatter.str(),
536 // access log flag and access log file name setting contents check.
537 if (element.access_log_flag == 1 && element.access_log_file_name == "") {
538 boost::format formatter("access log file name not set error");
539 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 3, formatter.str(), __FILE__, __LINE__);
540 err.setter(true, "access log file name not set error");
544 logger_implement_access *access_log_instance = NULL;
545 // access log instance create.
546 if (element.access_log_file_name != "") {
548 = logger_access_manager::getInstance().find_logger_implement_access(
549 element.access_log_file_name,
550 element.access_log_rotate_arguments,
552 if (access_log_instance == NULL) {
553 boost::format formatter("access logger Instance acquisition err = %s, "
554 "err.message = %s ");
555 formatter % (err ? "true" : "false") % err.get_message();
556 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 4, formatter.str(),
558 err.setter(true, "access log class instance create failed");
564 boost::asio::ip::address address = element.tcp_accept_endpoint.address();
565 #ifdef SCHED_SETAFFINITY
566 vsnic_cpumask = get_cpu_mask(address);
567 rsnic_cpumask = get_cpu_mask(param_data.nic_realserver_side);
571 boost::system::error_code acceptor_err;
572 acceptor_.open(element.tcp_accept_endpoint.protocol(), acceptor_err);
574 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 5, acceptor_err.message(),
576 err.setter(true, acceptor_err.message());
579 acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), acceptor_err);
581 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 6, acceptor_err.message(),
583 err.setter(true, acceptor_err.message());
586 if (likely(address.is_v6())) {
587 boost::asio::ip::v6_only option(true);
588 acceptor_.set_option(option, acceptor_err);
590 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 7, acceptor_err.message(),
592 err.setter(true, acceptor_err.message());
596 acceptor_.bind(element.tcp_accept_endpoint, acceptor_err);
598 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 8, acceptor_err.message(),
600 err.setter(true, acceptor_err.message());
604 //read replication data
605 read_replicationdata();
607 //load protocol module
608 protomod = protocol_module_control::getInstance().load_module(element.protocol_module_name);
609 if (NULL == protomod) {
611 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 9, PROTOMOD_LOAD_ERROR_MSG,
613 err.setter(true, PROTOMOD_LOAD_ERROR_MSG);
614 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
615 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
616 "l7vs::error_code& err ): err = %s, err.message = %s");
617 formatter % (err ? "true" : "false") % err.get_message();
618 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 43, formatter.str(),
623 //Protocol Module Initialize
624 protomod->init_logger_functions(
625 boost::bind(&Logger::getLogLevel, LOG_CAT_PROTOCOL),
626 boost::bind(&Logger::putLogFatal, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
627 boost::bind(&Logger::putLogError, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
628 boost::bind(&Logger::putLogWarn, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
629 boost::bind(&Logger::putLogInfo, LOG_CAT_PROTOCOL, _1, _2, _3, _4),
630 boost::bind(&Logger::putLogDebug, LOG_CAT_PROTOCOL, _1, _2, _3, _4));
631 protomod->initialize(
632 boost::bind(&virtualservice_tcp::rs_list_begin, this),
633 boost::bind(&virtualservice_tcp::rs_list_end, this),
634 boost::bind(&virtualservice_tcp::rs_list_next, this, _1),
635 boost::bind(&virtualservice_tcp::rs_list_lock, this),
636 boost::bind(&virtualservice_tcp::rs_list_unlock, this));
637 protomod->init_replication_functions(
638 boost::bind(&virtualservice_tcp::replication_pay_memory, this, _1, _2),
639 boost::bind(&virtualservice_tcp::replication_area_lock, this, element.protocol_module_name),
640 boost::bind(&virtualservice_tcp::replication_area_unlock, this, element.protocol_module_name),
641 element.tcp_accept_endpoint,
642 element.udp_recv_endpoint);
643 tcp_schedule_func_type sched_rs_func = boost::bind(
644 &virtualservice_tcp::schedule_rs, this, _1, _2, _3, _4, _5);
645 protomod->register_schedule(sched_rs_func);
647 protocol_module_base::check_message_result pm_result;
649 pm_result = protomod->check_parameter(element.protocol_args);
650 if (!pm_result.flag) {
651 err.setter(true, "Protocol Module argument error.");
652 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
653 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
654 "l7vs::error_code& err ): err = %s, err.message = %s");
655 formatter % (err ? "true" : "false") % err.get_message();
656 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 44, formatter.str(),
661 pm_result = protomod->set_parameter(element.protocol_args);
662 if (!pm_result.flag) {
663 err.setter(true, "Protocol Module argument error.");
664 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
665 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
666 "l7vs::error_code& err ): err = %s, err.message = %s");
667 formatter % (err ? "true" : "false") % err.get_message();
668 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 45, formatter.str(),
674 protomod->get_option_info(protocol_module_for_indication_options);
675 element.protocol_module_for_indication_options = protocol_module_for_indication_options;
677 //load schedule module
678 schedmod = schedule_module_control::getInstance().load_module(element.schedule_module_name);
679 if (NULL == schedmod) {
681 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 10, SCHEDMOD_LOAD_ERROR_MSG,
683 err.setter(true, SCHEDMOD_LOAD_ERROR_MSG);
684 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
685 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
686 "l7vs::error_code& err ) : err = %s, err.message = %s");
687 formatter % (err ? "true" : "false") % err.get_message();
688 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 46, formatter.str(),
693 //Schedule Module Initialize
694 schedmod->init_logger_functions(
695 boost::bind(&Logger::getLogLevel, LOG_CAT_SCHEDULE),
696 boost::bind(&Logger::putLogFatal, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
697 boost::bind(&Logger::putLogError, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
698 boost::bind(&Logger::putLogWarn, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
699 boost::bind(&Logger::putLogInfo, LOG_CAT_SCHEDULE, _1, _2, _3, _4),
700 boost::bind(&Logger::putLogDebug, LOG_CAT_SCHEDULE, _1, _2, _3, _4));
701 schedmod->initialize();
702 schedmod->init_replication_functions(
703 boost::bind(&virtualservice_tcp::replication_pay_memory, this, _1, _2),
704 boost::bind(&virtualservice_tcp::replication_area_lock, this, element.schedule_module_name),
705 boost::bind(&virtualservice_tcp::replication_area_unlock, this, element.schedule_module_name),
706 element.tcp_accept_endpoint,
707 element.udp_recv_endpoint);
709 // access log flag set
710 access_log_flag = false;
711 if (element.access_log_flag == 1) {
712 access_log_flag = true;
715 // access log rotation information set.
716 if (element.access_log_rotate_key_info == "") {
717 element.access_log_rotate_key_info = "none";
718 element.access_log_rotate_verbose_info = logger_access_manager::getInstance().get_rotate_default_verbose_displayed_contents();
720 element.access_log_rotate_verbose_info = element.access_log_rotate_key_info;
722 access_log_file_name = element.access_log_file_name;
723 access_log_rotate_arguments = element.access_log_rotate_arguments;
726 ssl_virtualservice_mode_flag = false;
727 ssl_file_name = element.ssl_file_name;
728 if (ssl_file_name != "") {
729 ssl_file_name = element.ssl_file_name;
731 if (unlikely(!get_ssl_parameter())) {
733 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 11, "get ssl parameter failed",
735 err.setter(true, "get ssl parameter failed");
738 // set SSL configuration
739 if (unlikely(!set_ssl_config())) {
741 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 12, "set ssl config failed",
743 err.setter(true, "set ssl config failed");
746 ssl_virtualservice_mode_flag = true;
752 //create session pool
754 for (int i = 0; i < param_data.session_pool_size; ++i) {
756 tcp_session *sess = new tcp_session(*this,
759 element.tcp_accept_endpoint,
760 ssl_virtualservice_mode_flag,
762 is_session_cache_use,
764 access_log_instance);
765 session_result_message result = sess->initialize();
766 if (result.flag == true) {
767 err.setter(result.flag, result.message);
768 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
769 boost::format formatter("out_function: "
770 "void virtualservice_tcp::initialize( "
771 "l7vs::error_code& err ): err = %s, "
773 formatter % (err ? "true" : "false") % err.get_message();
774 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 47,
775 formatter.str(), __FILE__, __LINE__);
779 session_thread_control *p_stc = new session_thread_control(
780 sess, vsnic_cpumask, rsnic_cpumask, -1);
781 p_stc->start_thread();
782 while (!pool_sessions.push(p_stc)) {}
785 LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "error, create session.",
788 err.setter(true, "error, create session.");
791 l7vs::error_code finalize_err;
792 finalize_err.setter(false, "");
793 finalize(finalize_err);
795 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
796 boost::format formatter("out_function: "
797 "void virtualservice_tcp::initialize( "
798 "l7vs::error_code& err ): err = %s, err.message = %s");
799 formatter % (err ? "true" : "false") % err.get_message();
800 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 48, formatter.str(),
806 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
807 boost::format fmt1("pool_session.size = %d");
808 fmt1 % pool_sessions.size();
809 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 49, fmt1.str(),
811 boost::format fmt2("active_session.size = %d");
812 fmt2 % active_sessions.size();
813 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 50, fmt2.str(),
818 err.setter(false, "");
820 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
821 boost::format formatter("out_function: void virtualservice_tcp::initialize( "
822 "l7vs::error_code& err ): err = %s, err.message = %s");
823 formatter % (err ? "true" : "false") % err.get_message();
824 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 51, formatter.str(),
830 * finalize virtualservice(TCP)
835 void l7vs::virtualservice_tcp::finalize(l7vs::error_code &err)
837 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
838 boost::format formatter("in_function: void virtualservice_tcp::finalize( "
839 "l7vs::error_code& err )");
840 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 52, formatter.str(),
842 boost::format fmt1("pool_session.size = %d");
843 fmt1 % pool_sessions.size();
844 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 53, fmt1.str(),
846 boost::format fmt2("active_session.size = %d");
847 fmt2 % active_sessions.size();
848 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 54, fmt2.str(),
854 while (active_sessions.size()) {
855 boost::this_thread::yield();
858 if (waiting_sessions.size() > 0) {
860 tcp_session *tmp_session = NULL;
861 session_thread_control *tmp_stc = NULL;
862 waiting_sessions.pop(tmp_session, tmp_stc);
867 if (likely(pool_sessions.push(tmp_stc))) {
874 //release sessions[i]->join();
875 while (!pool_sessions.empty()) {
876 session_thread_control *stc = pool_sessions.pop();
879 boost::mutex::scoped_lock upthread_wait(stc->get_upthread_mutex());
880 boost::mutex::scoped_lock downthread_wait(stc->get_downthread_mutex());
884 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
885 boost::format fmt("join pool session: pool_sessions.size = %d");
886 fmt % pool_sessions.size();
887 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 55, fmt.str(),
892 //unload ProtocolModule
894 //finalize ProtocolModule
895 protomod->finalize();
896 //unload ProtocolModule
897 protocol_module_control::getInstance().unload_module(protomod);
900 //unload ScheduleModule
902 schedule_module_control::getInstance().unload_module(schedmod);
906 active_sessions.clear();
907 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
908 boost::format fmt1("pool_session.size = %d");
909 fmt1 % pool_sessions.size();
910 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 56, fmt1.str(), __FILE__, __LINE__);
911 boost::format fmt2("active_session.size = %d");
912 fmt2 % active_sessions.size();
913 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 57, fmt2.str(), __FILE__, __LINE__);
916 //clear replication_data
917 bool replication_status = true;
918 replication &rep_noconst = const_cast<replication &>(rep);
920 if (replication::REPLICATION_SINGLE != rep_noconst.get_status()) {
921 unsigned int rep_size = 0;
922 replication_header *rep_header_ptr = reinterpret_cast<replication_header *>(
923 rep_noconst.pay_memory(REP_AREA_NAME, rep_size));
924 if ((rep_header_ptr == NULL) || (0 == rep_size)) {
925 err.setter(true, REP_BLOCK_SIZE_ERR_MSG);
926 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 6, REP_BLOCK_SIZE_ERR_MSG,
928 replication_status = false;
931 //check max data size
932 if ((rep_size * DATA_SIZE) <
933 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header))) {
934 err.setter(true, REP_AREA_SIZE_ERR_MSG);
935 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 7, REP_AREA_SIZE_ERR_MSG,
937 replication_status = false;
939 if ((NULL != rep_header_ptr) && (replication_status)) {
940 //lock replication area
941 rep_noconst.lock(REP_AREA_NAME);
943 rep_header_ptr->data_num = 0;
944 //unlock replication area
945 rep_noconst.unlock(REP_AREA_NAME);
949 //vsd.release_virtual_service( element );
950 if (access_log_file_name != "") {
951 // erase access log instance.
952 logger_access_manager::getInstance().erase_logger_implement_access(access_log_file_name, err);
954 boost::format fmt("access logger instance erase err:%s");
955 fmt % err.get_message();
956 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 8,
962 vsd.release_virtual_service(element);
964 err.setter(false, "");
966 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
967 boost::format formatter("out_function: void virtualservice_tcp::finalize( "
968 "l7vs::error_code& err ): err = %s, err.message = %s");
969 formatter % (err ? "true" : "false") % err.get_message();
970 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 58, formatter.str(), __FILE__, __LINE__);
976 * equal compare virtualservice(TCP)
978 * @param virtualservice_base
979 * @return bool ( true = equal )
981 bool l7vs::virtualservice_tcp::operator==(const l7vs::virtualservice_base &in)
983 boost::format formatter("function: void virtualservice_tcp::operator==( "
984 "const l7vs::virtualservice_base& in )");
985 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 59, formatter.str(), __FILE__, __LINE__);
987 virtualservice_base &vs = const_cast<virtualservice_base &>(in);
988 return ((element.tcp_accept_endpoint == vs.get_element().tcp_accept_endpoint)
989 && (element.udpmode == vs.get_element().udpmode));
993 * not-equal compare virtualservice(TCP)
995 * @param virtualservice_base
996 * @return bool ( true = not-equal )
998 bool l7vs::virtualservice_tcp::operator!=(const l7vs::virtualservice_base &in)
1000 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1001 boost::format formatter("in/out_function: void virtualservice_tcp::operator!=( "
1002 "const l7vs::virtualservice_base& in )");
1003 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 60, formatter.str(), __FILE__, __LINE__);
1005 virtualservice_base &vs = const_cast<virtualservice_base &>(in);
1006 return ((element.tcp_accept_endpoint != vs.get_element().tcp_accept_endpoint)
1007 || (element.udpmode != vs.get_element().udpmode));
1011 * add VirtualService( not-implement )
1013 * @param virtualservice_element
1017 void l7vs::virtualservice_tcp::set_virtualservice(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1019 err.setter(false, "");
1023 * edit VirtualService
1025 * @param virtualservice_element
1029 void l7vs::virtualservice_tcp::edit_virtualservice(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1031 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1032 boost::format formatter("in_function: void virtualservice_tcp::edit_virtualservice( "
1033 "const l7vs::virtualservice_element& in,"
1034 "l7vs::error_code& err ): dump in ");
1035 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 61, formatter.str(), __FILE__, __LINE__);
1038 virtualservice_element &elem = const_cast<virtualservice_element &>(in);
1039 if ((element.udpmode != elem.udpmode) ||
1040 (element.tcp_accept_endpoint != elem.tcp_accept_endpoint) ||
1041 (element.protocol_module_name != elem.protocol_module_name)) {
1042 err.setter(true, "Virtual Service does not exist.");
1043 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1044 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1045 "const l7vs::virtualservice_element& in,"
1046 "l7vs::error_code& err ): err = %s, err.message = %s");
1047 formatter % (err ? "true" : "false") % err.get_message();
1048 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 62, formatter.str(),
1049 __FILE__, __LINE__);
1054 //if change ScheduleModule Name, unload old ScheduleModule and load new ScheduleModule
1055 if ((element.schedule_module_name != elem.schedule_module_name) && ("" != elem.schedule_module_name)) {
1056 schedule_module_control::getInstance().unload_module(schedmod);
1057 schedmod = schedule_module_control::getInstance().load_module(elem.schedule_module_name);
1058 if (NULL == schedmod) {
1060 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 13, SCHEDMOD_LOAD_ERROR_MSG,
1061 __FILE__, __LINE__);
1062 err.setter(true, SCHEDMOD_LOAD_ERROR_MSG);
1063 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1064 boost::format formatter("out_function: "
1065 "void virtualservice_tcp::edit_virtualservice( "
1066 "const l7vs::virtualservice_element& in,"
1067 "l7vs::error_code& err ): err = %s, err.message = %s");
1068 formatter % (err ? "true" : "false") % err.get_message();
1069 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 63, formatter.str(),
1070 __FILE__, __LINE__);
1074 element.schedule_module_name = elem.schedule_module_name;
1077 //additional PM options(for protomod_url)
1078 protocol_module_base::check_message_result result;
1079 if( NULL != protomod ){
1080 result = protomod->add_parameter( elem.protocol_args );
1082 for( size_t i = 0; i < elem.protocol_args.size(); ++i ){
1083 element.protocol_args.push_back( elem.protocol_args[i] );
1086 err.setter( true, result.message );
1087 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1088 boost::format formatter("out_function: 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, 64, formatter.str(),
1093 __FILE__, __LINE__ );
1099 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 14, PROTOMOD_LOAD_ERROR_MSG,
1100 __FILE__, __LINE__ );
1101 err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
1102 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1103 boost::format formatter("out_function: void virtualservice_tcp::edit_virtualservice( "
1104 "const l7vs::virtualservice_element& in,"
1105 "l7vs::error_code& err ): err = %s, err.message = %s");
1106 formatter % ( err ? "true" : "false") % err.get_message();
1107 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 65, formatter.str(),
1108 __FILE__, __LINE__ );
1115 if (ULLONG_MAX == elem.qos_upstream) {
1116 element.qos_upstream = 0ULL;
1117 } else if (0ULL != elem.qos_upstream) {
1118 element.qos_upstream = elem.qos_upstream;
1121 if (ULLONG_MAX == elem.qos_downstream) {
1122 element.qos_downstream = 0ULL;
1123 } else if (0ULL != elem.qos_downstream) {
1124 element.qos_downstream = elem.qos_downstream;
1126 //sorry_maxconnection;
1127 if (LLONG_MAX == elem.sorry_maxconnection) {
1128 element.sorry_maxconnection = 0;
1129 } else if (0 != elem.sorry_maxconnection) {
1130 element.sorry_maxconnection = elem.sorry_maxconnection;
1133 if (INT_MAX == elem.sorry_flag) {
1134 element.sorry_flag = 0;
1135 } else if (0 != elem.sorry_flag) {
1136 element.sorry_flag = 1;
1139 if (virtualservice_element::FWD_NONE != elem.sorry_fwdmode) {
1140 element.sorry_fwdmode = elem.sorry_fwdmode;
1143 //if endpoint of SorryServer equal 255.255.255.255:0,not update
1144 //if equal endpoint 255.255.255.255:0, clear sorry parameters
1145 if (elem.sorry_endpoint ==
1146 boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("255.255.255.255"), (0))) {
1147 element.sorry_endpoint = boost::asio::ip::tcp::endpoint(
1148 boost::asio::ip::address::from_string("0.0.0.0"), (0));
1149 element.sorry_maxconnection = 0LL;
1150 element.sorry_flag = false;
1151 active_sessions.do_all(boost::bind(&session_thread_control::session_sorry_disable, _1));
1153 if (elem.sorry_endpoint != boost::asio::ip::tcp::endpoint(
1154 boost::asio::ip::address::from_string("0.0.0.0"), (0))) {
1155 element.sorry_endpoint = elem.sorry_endpoint;
1157 active_sessions.do_all(boost::bind(
1158 &session_thread_control::session_sorry_mode_change, _1, elem.sorry_flag));
1161 if (elem.access_log_flag != -1) {
1162 // access log flag ON and access log filename not set.
1163 if (elem.access_log_flag == 1 && element.access_log_file_name == "") {
1165 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 15, SCHEDMOD_LOAD_ERROR_MSG,
1166 __FILE__, __LINE__);
1167 err.setter(true, "access log flag change err.");
1171 // access log flag check and send access log output ON or OFF message to tcp_session
1172 element.access_log_flag = elem.access_log_flag;
1173 if (elem.access_log_flag == 1 && access_log_flag == false) {
1174 active_sessions.do_all(boost::bind(
1175 &session_thread_control::session_accesslog_output_mode_on, _1));
1176 access_log_flag = true;
1177 } else if (elem.access_log_flag == 0 && access_log_flag == true) {
1178 active_sessions.do_all(boost::bind(
1179 &session_thread_control::session_accesslog_output_mode_off, _1));
1180 access_log_flag = false;
1184 err.setter(false, "");
1186 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1187 boost::format formatter("out_function: void virtualservice_tcp::set_virtualservice( "
1188 "const l7vs::virtualservice_element& in,"
1189 "l7vs::error_code& err ): err = %s, err.message = %s");
1190 formatter % (err ? "true" : "false") % err.get_message();
1191 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 66, formatter.str(), __FILE__, __LINE__);
1198 * @param virtualservice_element
1202 void l7vs::virtualservice_tcp::add_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1204 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1205 boost::format formatter("in_function: void virtualservice_tcp::add_realserver( "
1206 "const l7vs::virtualservice_element& in,"
1207 "l7vs::error_code& err )");
1208 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 67, formatter.str(), __FILE__, __LINE__);
1211 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1213 //check equal virtualservice
1214 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1215 err.setter(true, "Virtual Service does not exist.");
1216 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1217 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1218 "const l7vs::virtualservice_element& in,"
1219 "l7vs::error_code& err ): err = %s, err.message = %s");
1220 formatter % (err ? "true" : "false") % err.get_message();
1221 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 68, formatter.str(),
1222 __FILE__, __LINE__);
1227 if (in.realserver_vector.size() == 0U) {
1228 err.setter(true, ".");
1229 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1230 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1231 "const l7vs::virtualservice_element& in,"
1232 "l7vs::error_code& err ): err = %s, err.message = %s");
1233 formatter % (err ? "true" : "false") % err.get_message();
1234 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 69, formatter.str(),
1235 __FILE__, __LINE__);
1239 //lock rs_list_ref_count_inc_mutex
1240 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1242 //waiting, rs_list_ref_count become 0
1243 while (rs_list_ref_count != 0ULL) {
1244 boost::this_thread::sleep(
1245 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1249 //check duplication realserver
1250 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1251 itr != in_element.realserver_vector.end();
1253 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1254 rs_itr != rs_list.end(); ++rs_itr) {
1255 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1256 err.setter(true, "Real Server already exist.");
1257 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1258 boost::format formatter("out_function: "
1259 "void virtualservice_tcp::add_realserver( "
1260 "const l7vs::virtualservice_element& in,"
1261 "l7vs::error_code& err ): err = %s, err.message = %s");
1262 formatter % (err ? "true" : "false") % err.get_message();
1263 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 70,
1264 formatter.str(), __FILE__, __LINE__);
1271 //pause active sessions
1272 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_on, _1));
1275 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1276 itr != in_element.realserver_vector.end();
1279 rs.tcp_endpoint = itr->tcp_endpoint;
1280 rs.udp_endpoint = itr->udp_endpoint;
1281 rs.weight = itr->weight;
1282 rs.fwdmode = itr->fwdmode;
1283 rs_list.push_back(rs);
1286 //run active sessions
1287 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1289 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1290 boost::format formatter("out_function: void virtualservice_tcp::add_realserver( "
1291 "const l7vs::virtualservice_element& in,"
1292 "l7vs::error_code& err ): err = %s, err.message = %s");
1293 formatter % (err ? "true" : "false") % err.get_message();
1294 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 71, formatter.str(), __FILE__, __LINE__);
1301 * @param virtualservice_element
1305 void l7vs::virtualservice_tcp::edit_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1307 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1308 boost::format formatter("in_function: void virtualservice_tcp::edit_realserver( "
1309 "const l7vs::virtualservice_element& in,"
1310 "l7vs::error_code& err )");
1311 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 72, formatter.str(), __FILE__, __LINE__);
1313 //check equal virtualservice
1314 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1315 err.setter(true, "Virtual Service does not exist.");
1316 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1317 boost::format formatter("out_function: void virtualservice_tcp::edit_realserver( "
1318 "const l7vs::virtualservice_element& in,"
1319 "l7vs::error_code& err ): err = %s, err.message = %s");
1320 formatter % (err ? "true" : "false") % err.get_message();
1321 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 73, formatter.str(),
1322 __FILE__, __LINE__);
1327 //lock rs_list_ref_count_inc_mutex
1328 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1330 //waiting, rs_list_ref_count become 0
1331 while (rs_list_ref_count != 0ULL) {
1332 boost::this_thread::sleep(
1333 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1337 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1339 //check is exist realserver
1340 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1341 itr != in_element.realserver_vector.end();
1343 bool exist_flag = false;
1344 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1345 rs_itr != rs_list.end(); ++rs_itr) {
1346 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1351 err.setter(true, "Real Server does not exist.");
1352 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1353 boost::format formatter("out_function: "
1354 "void virtualservice_tcp::edit_realserver( "
1355 "const l7vs::virtualservice_element& in,"
1356 "l7vs::error_code& err ): err = %s, err.message = %s");
1357 formatter % (err ? "true" : "false") % err.get_message();
1358 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 74, formatter.str(),
1359 __FILE__, __LINE__);
1365 //pause active sessions
1366 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_on, _1));
1369 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1370 itr != in_element.realserver_vector.end();
1372 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1373 rs_itr != rs_list.end(); ++rs_itr) {
1374 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1375 rs_itr->udp_endpoint = itr->udp_endpoint;
1377 if (itr->weight != -1) {
1378 rs_itr->weight = itr->weight;
1380 if (itr->fwdmode != realserver_element::FWD_NONE) {
1381 rs_itr->fwdmode = itr->fwdmode;
1387 //run active sessions
1388 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1390 err.setter(false, "");
1391 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1392 boost::format formatter("out_function: void virtualservice_tcp::edit_realserver( "
1393 "const l7vs::virtualservice_element& in,"
1394 "l7vs::error_code& err ): err = %s, err.message = %s");
1395 formatter % (err ? "true" : "false") % err.get_message();
1396 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 75, formatter.str(), __FILE__, __LINE__);
1403 * @param virtualservice_element
1407 void l7vs::virtualservice_tcp::del_realserver(const l7vs::virtualservice_element &in, l7vs::error_code &err)
1409 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1410 boost::format formatter("in_function: void virtualservice_tcp::del_realserver( "
1411 "const l7vs::virtualservice_element& in,"
1412 "l7vs::error_code& err )");
1413 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 76, formatter.str(), __FILE__, __LINE__);
1416 //check equal virtualservice
1417 if ((element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint)) {
1418 err.setter(true, "Virtual Service is not equal.");
1419 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1420 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1421 "const l7vs::virtualservice_element& in,"
1422 "l7vs::error_code& err ): err = %s, err.message = %s");
1423 formatter % (err ? "true" : "false") % err.get_message();
1424 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 77, formatter.str(),
1425 __FILE__, __LINE__);
1430 //lock rs_list_ref_count_inc_mutex
1431 rw_scoped_lock inc_lock(rs_list_ref_count_inc_mutex);
1433 //waiting, rs_list_ref_count become 0
1434 while (rs_list_ref_count != 0ULL) {
1435 boost::this_thread::sleep(
1436 boost::posix_time::milliseconds(virtualservice_base::REFCOUNT_WAIT_INTERVAL)
1440 virtualservice_element &in_element = const_cast<virtualservice_element &>(in);
1442 //check is exist realserver
1443 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1444 itr != in_element.realserver_vector.end();
1446 bool exist_flag = false;
1447 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1448 rs_itr != rs_list.end(); ++rs_itr) {
1449 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1454 err.setter(true, "Real Server does not exist.");
1455 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1456 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1457 "const l7vs::virtualservice_element& in,"
1458 "l7vs::error_code& err ): err = %s, err.message = %s");
1459 formatter % (err ? "true" : "false") % err.get_message();
1460 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 78, formatter.str(),
1461 __FILE__, __LINE__);
1467 //pause active sessions
1468 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_on, _1));
1471 for (std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1472 itr != in_element.realserver_vector.end();
1474 for (std::list<realserver>::iterator rs_itr = rs_list.begin();
1475 rs_itr != rs_list.end(); ++rs_itr) {
1476 if (itr->tcp_endpoint == rs_itr->tcp_endpoint) {
1477 rs_list.erase(rs_itr);
1483 //run active sessions
1484 active_sessions.do_all(boost::bind(&session_thread_control::session_pause_off, _1));
1486 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1487 boost::format formatter("out_function: void virtualservice_tcp::del_realserver( "
1488 "const l7vs::virtualservice_element& in,"
1489 "l7vs::error_code& err ): err = %s, err.message = %s");
1490 formatter % (err ? "true" : "false") % err.get_message();
1491 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 79, formatter.str(), __FILE__, __LINE__);
1496 * main loop of virtualservice(TCP)
1501 void l7vs::virtualservice_tcp::run()
1503 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function: void virtualservice_tcp::run()",
1504 __FILE__, __LINE__);
1506 if (pool_sessions.size() == 0) {
1507 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.",
1508 __FILE__, __LINE__);
1511 boost::asio::socket_base::receive_buffer_size option(8192 * 192);
1512 acceptor_.set_option(option);
1513 //set socket option TCP_DEFER_ACCEPT
1514 if (defer_accept_opt) {
1515 size_t len = sizeof(defer_accept_val);
1516 int err = ::setsockopt(acceptor_.native(), IPPROTO_TCP, TCP_DEFER_ACCEPT, &defer_accept_val, len);
1517 if (unlikely(err)) {
1519 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
1520 "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__);
1526 //left session is less than the threshold
1527 if ((sessionpool_alert_flag == false) &&
1528 (pool_sessions.size() < param_data.session_pool_alert_on)) {
1529 //create trap message
1530 trapmessage trap_msg;
1531 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_ON;
1532 trap_msg.message = "TRAP00020011,Warning: The left-session has fell below the threshold of left-session warning.";
1533 error_code err_code;
1534 //push the trap message
1535 snmpagent::push_trapmessage(trap_msg, err_code);
1537 std::string msg("Push trap message failed.");
1538 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 40, msg, __FILE__, __LINE__);
1541 //set sessionpool alert flag true
1542 sessionpool_alert_flag = true;
1545 //switch active a session
1546 session_thread_control *stc_ptr;
1548 stc_ptr = pool_sessions.pop();
1552 //register accept event handler
1553 waiting_sessions.insert(stc_ptr->get_session().get(), stc_ptr);
1555 if (!ssl_virtualservice_mode_flag) {
1556 acceptor_.async_accept(stc_ptr->get_session()->get_client_socket(),
1557 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1558 boost::asio::placeholders::error));
1560 acceptor_.async_accept(stc_ptr->get_session()->get_client_ssl_socket().lowest_layer(),
1561 boost::bind(&virtualservice_tcp::handle_accept, this, stc_ptr,
1562 boost::asio::placeholders::error));
1564 //register timer event handler
1565 calc_bps_timer->expires_from_now(boost::posix_time::milliseconds(param_data.bps_interval));
1566 calc_bps_timer->async_wait(boost::bind(&virtualservice_tcp::handle_throughput_update,
1567 this, boost::asio::placeholders::error));
1569 //register handle_replication_interrupt
1570 replication_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1571 replication_timer->async_wait(boost::bind(&virtualservice_tcp::handle_replication_interrupt,
1572 this, boost::asio::placeholders::error));
1573 //register handle_protomod_replication
1574 protomod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1575 protomod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_protomod_replication,
1576 this, boost::asio::placeholders::error));
1577 //register handle_schedmod_replication
1578 schedmod_rep_timer->expires_from_now(boost::posix_time::milliseconds(param_data.rep_interval));
1579 schedmod_rep_timer->async_wait(boost::bind(&virtualservice_tcp::handle_schedmod_replication,
1580 this, boost::asio::placeholders::error));
1582 //run dispatcher(start io_service loop)
1585 //stop all active sessions
1587 active_sessions.do_all(boost::bind(&session_thread_control::session_stop, _1));
1597 void l7vs::virtualservice_tcp::stop()
1599 Logger funcLog(LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function: void virtualservice_tcp::stop()",
1600 __FILE__, __LINE__);
1602 boost::system::error_code err;
1603 virtualservice_stop_flag++;
1604 while (interrupt_running_flag.get()) {
1605 boost::this_thread::yield();
1608 acceptor_.close(err);
1610 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__);
1614 calc_bps_timer->cancel();
1615 replication_timer->cancel();
1616 protomod_rep_timer->cancel();
1617 schedmod_rep_timer->cancel();
1624 * increment active-connection count
1629 void l7vs::virtualservice_tcp::connection_active(const boost::asio::ip::tcp::endpoint &in)
1631 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1632 boost::format formatter("in_function: void virtualservice_tcp::connection_active( "
1633 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1635 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__);
1638 for (std::list<realserver>::iterator itr = rs_list.begin();
1639 itr != rs_list.end();
1641 if (itr->tcp_endpoint == in) {
1642 itr->increment_active();
1649 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1650 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 83, "out_function: "
1651 "void virtualservice_tcp::connection_active()", __FILE__, __LINE__);
1656 * increment in-active-connection (and decrement active-connection count)
1661 void l7vs::virtualservice_tcp::connection_inactive(const boost::asio::ip::tcp::endpoint &in)
1663 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1664 boost::format formatter("in_function: void virtualservice_tcp::connection_inactive( "
1665 "const boost::asio::ip::tcp::endpoint& in ): in = %s");
1667 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__);
1670 for (std::list<realserver>::iterator itr = rs_list.begin();
1671 itr != rs_list.end();
1673 if (itr->tcp_endpoint == in) {
1674 itr->decrement_active();
1675 itr->increment_inact();
1682 //left session is more than the release threshold
1683 if ((sessionpool_alert_flag == true) &&
1684 ((pool_sessions.size() + waiting_sessions.size()) > param_data.session_pool_alert_off)) {
1685 //create trap message
1686 trapmessage trap_msg;
1687 trap_msg.type = trapmessage::SESSIONPOOL_ALERT_OFF;
1688 trap_msg.message = "TRAP00020012,Warning release: The left-session has exceeded the release threshold of left-session warning.";
1689 error_code err_code;
1690 //push the trap message
1691 snmpagent::push_trapmessage(trap_msg, err_code);
1693 std::string msg("Push trap message failed.");
1694 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 39, msg, __FILE__, __LINE__);
1697 //set sessionpool alert flag true
1698 sessionpool_alert_flag = false;
1701 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1702 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 85, "out_function: "
1703 "void virtualservice_tcp::connection_inactive()", __FILE__, __LINE__);
1713 void l7vs::virtualservice_tcp::release_session(const tcp_session *session_ptr)
1715 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1716 boost::format funclog_fmt("in_function: void virtualservice_tcp::release_session( "
1717 "const tcp_session* session_ptr ): session_ptr = %d");
1718 funclog_fmt % session_ptr;
1719 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 86, funclog_fmt.str(), __FILE__, __LINE__);
1722 session_thread_control *stc_ptr = active_sessions.find(session_ptr);
1723 if (unlikely(NULL == stc_ptr)) {
1724 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1725 boost::format fmt("session release fail: "
1726 "active_sessions.find( const tcp_session* session_ptr = %d )");
1728 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 87, fmt.str(), __FILE__, __LINE__);
1729 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 88, "out_function: "
1730 "void virtualservice_tcp::release_session( "
1731 "const boost::thread::id thread_id )", __FILE__, __LINE__);
1736 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1737 boost::format fmt1("pool_session.size = %d");
1738 fmt1 % pool_sessions.size();
1739 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 89, fmt1.str(), __FILE__, __LINE__);
1740 boost::format fmt2("active_session.size = %d");
1741 fmt2 % active_sessions.size();
1742 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 90, fmt2.str(), __FILE__, __LINE__);
1743 boost::format fmt3("active_count = %d");
1744 fmt3 % active_count.get();
1745 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 91, fmt3.str(), __FILE__, __LINE__);
1747 active_sessions.erase(session_ptr);
1748 stc_ptr->get_session()->initialize();
1750 if (likely(pool_sessions.push(stc_ptr))) {
1755 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1756 boost::format fmt1("pool_session.size = %d");
1757 fmt1 % pool_sessions.size();
1758 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 92, fmt1.str(), __FILE__, __LINE__);
1759 boost::format fmt2("active_session.size = %d");
1760 fmt2 % active_sessions.size();
1761 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 93, fmt2.str(), __FILE__, __LINE__);
1762 boost::format fmt3("active_count = %d");
1763 fmt3 % active_count.get();
1764 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 94, fmt3.str(), __FILE__, __LINE__);
1766 boost::format funclog_fmt("out_function: void virtualservice_tcp::release_session( "
1767 "const tcp_session* session_ptr ): session_ptr = %d");
1768 funclog_fmt % session_ptr;
1769 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 95, funclog_fmt.str(), __FILE__, __LINE__);
1774 // set_socket_option
1776 void l7vs::virtualservice_tcp::set_socket_option()
1779 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1780 boost::format funclog_fmt("in_function: void virtualservice_tcp::et_socket_option");
1781 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 96, funclog_fmt.str(), __FILE__, __LINE__);
1784 // socket option check & set
1785 //! TCP_DEFER_ACCEPT (false:not set,true:set option)
1786 defer_accept_opt = false;
1787 //! TCP_DEFER_ACCEPT option value
1788 defer_accept_val = 0;
1789 //! TCP_NODELAY (false:not set,true:set option)
1790 set_sock_opt.nodelay_opt = false;
1791 //! TCP_NODELAY option value (false:off,true:on)
1792 set_sock_opt.nodelay_val = false;
1793 //! TCP_CORK (false:not set,true:set option)
1794 set_sock_opt.cork_opt = false;
1795 //! TCP_CORK option value (false:off,true:on)
1796 set_sock_opt.cork_val = false;
1797 //! TCP_QUICKACK (false:not set,true:set option)
1798 set_sock_opt.quickack_opt = false;
1799 //! TCP_QUICKACK option value (false:off,true:on)
1800 set_sock_opt.quickack_val = false;
1802 // set socket option
1803 if (element.socket_option_tcp_defer_accept != 0) {
1804 defer_accept_opt = true;
1805 if (element.socket_option_tcp_defer_accept == 1) {
1806 defer_accept_val = 1;
1810 if (element.socket_option_tcp_nodelay != 0) {
1811 set_sock_opt.nodelay_opt = true;
1812 if (element.socket_option_tcp_nodelay == 1) {
1813 set_sock_opt.nodelay_val = true;
1817 if (element.socket_option_tcp_cork != 0) {
1818 set_sock_opt.cork_opt = true;
1819 if (element.socket_option_tcp_cork == 1) {
1820 set_sock_opt.cork_val = true;
1824 if (element.socket_option_tcp_quickack != 0) {
1825 set_sock_opt.quickack_opt = true;
1826 if (element.socket_option_tcp_quickack == 1) {
1827 set_sock_opt.quickack_val = true;
1831 //----Debug log----------------------------------------------------------------------
1832 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1833 boost::format formatter("set_socket_option"
1834 " defer_accept_opt[%s]"
1835 " defer_accept_val[%d]"
1841 " quickack_val[%s]");
1843 % (defer_accept_opt ? "true" : "false")
1845 % (set_sock_opt.nodelay_opt ? "true" : "false")
1846 % (set_sock_opt.nodelay_val ? "true" : "false")
1847 % (set_sock_opt.cork_opt ? "true" : "false")
1848 % (set_sock_opt.cork_val ? "true" : "false")
1849 % (set_sock_opt.quickack_opt ? "true" : "false")
1850 % (set_sock_opt.quickack_val ? "true" : "false");
1851 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 97, formatter.str(), __FILE__, __LINE__);
1853 //----Debug log----------------------------------------------------------------------
1857 //! get private key file password (for callback function)
1858 //! @return password string
1859 std::string l7vs::virtualservice_tcp::get_ssl_password()
1861 //*-------- DEBUG LOG --------*/
1862 if (unlikely(LOG_LV_DEBUG ==
1863 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1864 std::stringstream buf;
1865 buf << "in_function: ";
1866 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password()";
1867 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 98, buf.str(),
1868 __FILE__, __LINE__);
1870 //*------ DEBUG LOG END ------*/
1872 // Get password from file.
1873 std::string retstr = "";
1875 char buf[MAX_SSL_PASSWD_SIZE + 3];
1876 if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1878 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1879 "Password file cannot open.", __FILE__, __LINE__);
1881 if (fgets(buf, MAX_SSL_PASSWD_SIZE + 3, fp) == NULL) {
1882 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
1883 "Password not found in file.",
1884 __FILE__, __LINE__);
1886 if (strlen(buf) > MAX_SSL_PASSWD_SIZE) {
1887 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1888 "Password is too long.",
1889 __FILE__, __LINE__);
1891 buf[strlen(buf) - 1] = '\0';
1898 //*-------- DEBUG LOG --------*/
1899 if (unlikely(LOG_LV_DEBUG ==
1900 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1901 std::stringstream buf;
1902 buf << "out_function: ";
1903 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password(): ";
1904 buf << "retstr = " << retstr;
1905 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 99, buf.str(),
1906 __FILE__, __LINE__);
1908 //*------ DEBUG LOG END ------*/
1914 //! Convert verify option string to integer(#define).
1916 //! @param[in] opt_string option string
1917 //! @retval ret option value
1918 //! @retval -1 no match
1919 int l7vs::virtualservice_tcp::conv_verify_option(std::string opt_string)
1921 //*-------- DEBUG LOG --------*/
1922 if (unlikely(LOG_LV_DEBUG ==
1923 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1924 std::stringstream buf;
1925 buf << "in_function: ";
1926 buf << "int virtualservice_tcp::conv_verify_option";
1927 buf << "(std::string opt_string): ";
1928 buf << "opt_string = " << opt_string;
1929 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 100, buf.str(),
1930 __FILE__, __LINE__);
1932 //*------ DEBUG LOG END ------*/
1936 // /usr/include/openssl/ssl.h
1937 // #define SSL_VERIFY_NONE 0x00
1938 // #define SSL_VERIFY_PEER 0x01
1939 // #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
1940 // #define SSL_VERIFY_CLIENT_ONCE 0x04
1942 if (opt_string == "SSL_VERIFY_NONE") {
1943 ret = SSL_VERIFY_NONE;
1944 } else if (opt_string == "SSL_VERIFY_PEER") {
1945 ret = SSL_VERIFY_PEER;
1946 } else if (opt_string == "SSL_VERIFY_FAIL_IF_NO_PEER_CERT") {
1947 ret = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1948 } else if (opt_string == "SSL_VERIFY_CLIENT_ONCE") {
1949 ret = SSL_VERIFY_CLIENT_ONCE;
1951 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
1952 "verify option string no match.",
1953 __FILE__, __LINE__);
1956 //*-------- DEBUG LOG --------*/
1957 if (unlikely(LOG_LV_DEBUG ==
1958 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1959 std::stringstream buf;
1960 buf << "out_function: ";
1961 buf << "int virtualservice_tcp::conv_verify_option";
1962 buf << "(std::string opt_string): ";
1963 buf << "return_value = " << ret;
1964 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 101, buf.str(),
1965 __FILE__, __LINE__);
1967 //*------ DEBUG LOG END ------*/
1968 // if ret == -1 then No match.
1973 // Convert SSL option string to integer(#define).
1975 // @param[in] opt_string option string
1976 // @retval ret option value
1977 // @retval -1 no match
1978 long int l7vs::virtualservice_tcp::conv_ssl_option(std::string opt_string)
1980 //*-------- DEBUG LOG --------*/
1981 if (unlikely(LOG_LV_DEBUG ==
1982 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1983 std::stringstream buf;
1984 buf << "in_function: ";
1985 buf << "long int virtualservice_tcp::conv_ssl_option";
1986 buf << "(std::string opt_string): ";
1987 buf << "opt_string = " << opt_string;
1988 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 102, buf.str(),
1989 __FILE__, __LINE__);
1991 //*------ DEBUG LOG END ------*/
1995 // /usr/include/openssl/ssl.h
1996 // #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
1997 // #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
1998 // #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
1999 // #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
2000 // #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
2001 // #define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L
2002 // #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
2003 // #define SSL_OP_TLS_D5_BUG 0x00000100L
2004 // #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
2005 // #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L
2006 // #define SSL_OP_ALL 0x00000FF7L
2007 // #define SSL_OP_NO_QUERY_MTU 0x00001000L
2008 // #define SSL_OP_COOKIE_EXCHANGE 0x00002000L
2009 // #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
2010 // #define SSL_OP_SINGLE_ECDH_USE 0x00080000L
2011 // #define SSL_OP_SINGLE_DH_USE 0x00100000L
2012 // #define SSL_OP_EPHEMERAL_RSA 0x00200000L
2013 // #define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
2014 // #define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
2015 // #define SSL_OP_NO_SSLv2 0x01000000L
2016 // #define SSL_OP_NO_SSLv3 0x02000000L
2017 // #define SSL_OP_NO_TLSv1 0x04000000L
2018 // #define SSL_OP_PKCS1_CHECK_1 0x08000000L
2019 // #define SSL_OP_PKCS1_CHECK_2 0x10000000L
2020 // #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
2021 // #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
2022 if (opt_string == "SSL_OP_MICROSOFT_SESS_ID_BUG") {
2023 ret = SSL_OP_MICROSOFT_SESS_ID_BUG;
2024 } else if (opt_string == "SSL_OP_NETSCAPE_CHALLENGE_BUG") {
2025 ret = SSL_OP_NETSCAPE_CHALLENGE_BUG;
2026 } else if (opt_string == "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG") {
2027 ret = SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
2028 } else if (opt_string == "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG") {
2029 ret = SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
2030 } else if (opt_string == "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER") {
2031 ret = SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
2032 } else if (opt_string == "SSL_OP_MSIE_SSLV2_RSA_PADDING") {
2033 ret = SSL_OP_MSIE_SSLV2_RSA_PADDING;
2034 } else if (opt_string == "SSL_OP_SSLEAY_080_CLIENT_DH_BUG") {
2035 ret = SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
2036 } else if (opt_string == "SSL_OP_TLS_D5_BUG") {
2037 ret = SSL_OP_TLS_D5_BUG;
2038 } else if (opt_string == "SSL_OP_TLS_BLOCK_PADDING_BUG") {
2039 ret = SSL_OP_TLS_BLOCK_PADDING_BUG;
2040 } else if (opt_string == "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS") {
2041 ret = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
2042 } else if (opt_string == "SSL_OP_ALL") {
2043 // boost::asio::ssl::context::default_workarounds
2045 } else if (opt_string == "SSL_OP_NO_QUERY_MTU") {
2046 ret = SSL_OP_NO_QUERY_MTU;
2047 } else if (opt_string == "SSL_OP_COOKIE_EXCHANGE") {
2048 ret = SSL_OP_COOKIE_EXCHANGE;
2049 } else if (opt_string == "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION") {
2050 ret = SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
2051 } else if (opt_string == "SSL_OP_SINGLE_ECDH_USE") {
2052 ret = SSL_OP_SINGLE_ECDH_USE;
2053 } else if (opt_string == "SSL_OP_SINGLE_DH_USE") {
2054 // boost::asio::ssl::context::single_dh_use
2055 ret = SSL_OP_SINGLE_DH_USE;
2056 } else if (opt_string == "SSL_OP_EPHEMERAL_RSA") {
2057 ret = SSL_OP_EPHEMERAL_RSA;
2058 } else if (opt_string == "SSL_OP_CIPHER_SERVER_PREFERENCE") {
2059 ret = SSL_OP_CIPHER_SERVER_PREFERENCE;
2060 } else if (opt_string == "SSL_OP_TLS_ROLLBACK_BUG") {
2061 ret = SSL_OP_TLS_ROLLBACK_BUG;
2062 } else if (opt_string == "SSL_OP_NO_SSLv2") {
2063 // boost::asio::ssl::context::no_sslv2
2064 ret = SSL_OP_NO_SSLv2;
2065 } else if (opt_string == "SSL_OP_NO_SSLv3") {
2066 // boost::asio::ssl::context::no_sslv3
2067 ret = SSL_OP_NO_SSLv3;
2068 } else if (opt_string == "SSL_OP_NO_TLSv1") {
2069 // boost::asio::ssl::context::no_tlsv1
2070 ret = SSL_OP_NO_TLSv1;
2071 } else if (opt_string == "SSL_OP_PKCS1_CHECK_1") {
2072 ret = SSL_OP_PKCS1_CHECK_1;
2073 } else if (opt_string == "SSL_OP_PKCS1_CHECK_2") {
2074 ret = SSL_OP_PKCS1_CHECK_2;
2075 } else if (opt_string == "SSL_OP_NETSCAPE_CA_DN_BUG") {
2076 ret = SSL_OP_NETSCAPE_CA_DN_BUG;
2077 } else if (opt_string == "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG") {
2078 ret = SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
2080 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
2081 "ssl option string no match.",
2082 __FILE__, __LINE__);
2085 //*-------- DEBUG LOG --------*/
2086 if (unlikely(LOG_LV_DEBUG ==
2087 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2088 std::stringstream buf;
2089 buf << "out_function: ";
2090 buf << "long int virtualservice_tcp::conv_ssl_option";
2091 buf << "(std::string opt_string): ";
2092 buf << "return_value = " << ret;
2093 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 103, buf.str(),
2094 __FILE__, __LINE__);
2096 //------ DEBUG LOG END ------*/
2097 // if ret == -1 then No match.
2102 //! get ssl parameter
2103 //! @return get ssl parameter result
2104 bool l7vs::virtualservice_tcp::get_ssl_parameter()
2106 //*-------- DEBUG LOG --------*/
2107 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2108 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 104,
2109 "in_function: bool virtualservice_tcp::get_ssl_parameter()",
2110 __FILE__, __LINE__);
2112 //*------ DEBUG LOG END ------*/
2113 typedef std::vector< std::string > string_vector_type;
2116 string_vector_type string_vector;
2117 l7vs::error_code err;
2118 bool retbool = false;
2121 // param init ( ssl configuration file )
2122 if (unlikely(!param.init(l7vs::PARAM_COMP_SSL, ssl_file_name))) {
2123 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 24,
2124 "SSL config file read error.",
2125 __FILE__, __LINE__);
2129 //// SSL context parameter
2130 // Get parameter "ca_dir".
2131 ca_dir = param.get_string(l7vs::PARAM_COMP_SSL, "ca_dir",
2132 err, ssl_file_name);
2133 if (unlikely(err) || ca_dir == "") {
2134 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 9,
2135 "ca_dir parameter not found. Use default value.",
2136 __FILE__, __LINE__);
2137 ca_dir = DEFAULT_SSL_CA_DIR;
2140 // Get parameter "ca_file".
2141 ca_file = param.get_string(l7vs::PARAM_COMP_SSL, "ca_file",
2142 err, ssl_file_name);
2143 if (unlikely(err)) {
2144 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 25,
2145 "Cannot get ca_file parameter.",
2146 __FILE__, __LINE__);
2150 // Get parameter "cert_chain_dir".
2151 cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2155 if (unlikely(err) || cert_chain_dir == "") {
2156 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 10,
2157 "cert_chain_dir parameter not found. Use default value.",
2158 __FILE__, __LINE__);
2159 cert_chain_dir = DEFAULT_SSL_CERT_CHAIN_DIR;
2162 // Get parameter "cert_chain_file".
2163 cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
2167 if (unlikely(err) || cert_chain_file == "") {
2168 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 26,
2169 "Cannot get cert_chain_file parameter.",
2170 __FILE__, __LINE__);
2174 // Get parameter "private_key_dir".
2175 private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2179 if (unlikely(err) || private_key_dir == "") {
2180 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 11,
2181 "private_key_dir parameter not found. Use default value.",
2182 __FILE__, __LINE__);
2183 private_key_dir = DEFAULT_SSL_PRIVATE_KEY_DIR;
2186 // Get parameter "private_key_file".
2187 private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
2191 if (unlikely(err) || private_key_file == "") {
2192 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 27,
2193 "Cannot get private_key_file parameter.",
2194 __FILE__, __LINE__);
2198 // Get parameter "private_key_filetype".
2199 // and convert string to filetype define value.
2201 // /usr/include/openssl/ssl.h
2202 // #define SSL_FILETYPE_PEM X509_FILETYPE_PEM ->1
2203 // #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 ->2
2204 std::string filetype_str = param.get_string(
2205 l7vs::PARAM_COMP_SSL,
2206 "private_key_filetype",
2209 if (unlikely(err) || filetype_str == "") {
2210 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 12,
2211 "private_key_filetype parameter not found. Use default value.",
2212 __FILE__, __LINE__);
2213 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
2214 } else if (filetype_str == "SSL_FILETYPE_PEM") {
2215 private_key_filetype = boost::asio::ssl::context::pem;
2216 } else if (filetype_str == "SSL_FILETYPE_ASN1") {
2217 private_key_filetype = boost::asio::ssl::context::asn1;
2219 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
2220 "private_key_filetype convert error.",
2221 __FILE__, __LINE__);
2225 // Get parameter "private_key_passwd_dir".
2226 private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2227 "private_key_passwd_dir",
2230 if (unlikely(err) || private_key_passwd_dir == "") {
2231 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 13,
2232 "private_key_passwd_dir parameter not found. Use default value.",
2233 __FILE__, __LINE__);
2234 private_key_passwd_dir = DEFAULT_SSL_PRIVATE_KEY_PASSWD_DIR;
2237 // Get parameter "private_key_passwd_file".
2238 private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2239 "private_key_passwd_file",
2242 if (unlikely(err) || private_key_passwd_file == "") {
2243 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
2244 "Cannot get private_key_passwd_file parameter.",
2245 __FILE__, __LINE__);
2249 // Get parameter "verify_options".
2250 param.get_multistring(l7vs::PARAM_COMP_SSL,
2255 if (unlikely(err)) {
2256 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 14,
2257 "verify_options parameter not found. Use default value.",
2258 __FILE__, __LINE__);
2259 verify_options = DEFAULT_SSL_VERIFY_OPTIONS;
2261 // Make verify option bit data.
2262 for (string_vector_type::iterator itr = string_vector.begin();
2263 itr != string_vector.end(); ++itr) {
2264 // Convert string to define value.
2265 int int_val = conv_verify_option(*itr);
2266 if (unlikely(int_val == -1)) {
2267 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 30,
2268 "verify_options convert error.",
2269 __FILE__, __LINE__);
2272 verify_options = (verify_options | int_val);
2276 // Get parameter "verify_cert_depth".
2277 verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2278 "verify_cert_depth",
2281 if (unlikely(err)) {
2282 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 15,
2283 "verify_cert_depth parameter not found. Use default value.",
2284 __FILE__, __LINE__);
2285 verify_cert_depth = DEFAULT_SSL_VERIFY_CERT_DEPTH;
2286 } else if (unlikely(verify_cert_depth < 0 ||
2287 verify_cert_depth > INT_MAX)) {
2288 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 31,
2289 "Invalid verify_cert_depth parameter value.",
2290 __FILE__, __LINE__);
2294 // Get parameter "ssl_options".
2295 // and Check dh parameter file use or not.
2296 is_tmp_dh_use = false;
2297 param.get_multistring(l7vs::PARAM_COMP_SSL,
2302 if (unlikely(err)) {
2303 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 16,
2304 "ssl_options parameter not found. Use default value.",
2305 __FILE__, __LINE__);
2306 ssl_options = DEFAULT_SSL_OPTIONS;
2307 is_tmp_dh_use = true;
2309 // Make ssl option bit data.
2310 for (string_vector_type::iterator itr = string_vector.begin();
2311 itr != string_vector.end(); ++itr) {
2312 // Convert string to define value.
2313 long int longint_val = conv_ssl_option(*itr);
2314 if (unlikely(longint_val == -1)) {
2315 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 32,
2316 "ssl_options convert error.",
2317 __FILE__, __LINE__);
2319 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2320 is_tmp_dh_use = true;
2322 ssl_options = (ssl_options | longint_val);
2326 if (is_tmp_dh_use) {
2327 // Get parameter "tmp_dh_dir".
2328 tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2332 if (unlikely(err) || tmp_dh_dir == "") {
2333 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
2334 "tmp_dh_dir parameter not found. Use default value.",
2335 __FILE__, __LINE__);
2336 tmp_dh_dir = DEFAULT_SSL_TMP_DH_DIR;
2338 // Get parameter "tmp_dh_file".
2339 tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2343 if (unlikely(err) || tmp_dh_file == "") {
2344 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 33,
2345 "Cannot get tmp_dh_file parameter.",
2346 __FILE__, __LINE__);
2351 // Get parameter "cipher_list".
2352 cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2356 if (unlikely(err) || cipher_list == "") {
2357 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 18,
2358 "cipher_list parameter not found. Use default value.",
2359 __FILE__, __LINE__);
2360 cipher_list = DEFAULT_SSL_CIPHER_LIST;
2363 //// SSL session cache parameter
2364 // Get parameter "session_cache".
2365 is_session_cache_use = false;
2366 std::string cache_str = param.get_string(l7vs::PARAM_COMP_SSL,
2370 if (unlikely(err) || cache_str == "") {
2371 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
2372 "session_cache parameter not found. Use default value.",
2373 __FILE__, __LINE__);
2374 is_session_cache_use = true;
2375 } else if (cache_str == "on") {
2376 is_session_cache_use = true;
2377 } else if (cache_str == "off") {
2378 is_session_cache_use = false;
2380 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2381 "Invalid session_cache parameter value.", __FILE__, __LINE__);
2385 if (is_session_cache_use) {
2386 session_cache_mode = DEFAULT_SSL_SESSION_CACHE_MODE;
2387 // Get parameter "session_cache_size".
2388 session_cache_size = param.get_int(l7vs::PARAM_COMP_SSL,
2389 "session_cache_size",
2392 if (unlikely(err)) {
2393 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
2394 "session_cache_size parameter not found. Use default value.",
2395 __FILE__, __LINE__);
2396 session_cache_size = DEFAULT_SSL_SESSION_CACHE_SIZE;
2397 } else if (session_cache_size < 0 ||
2398 session_cache_size > INT_MAX) {
2399 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 35,
2400 "Invalid session_cache_size parameter value.", __FILE__, __LINE__);
2403 // Get parameter "session_cache_timeout".
2404 session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2405 "session_cache_timeout",
2408 if (unlikely(err)) {
2409 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
2410 "session_cache_timeout parameter not found. Use default value.",
2411 __FILE__, __LINE__);
2412 session_cache_timeout = DEFAULT_SSL_SESSION_CACHE_TIMEOUT;
2413 } else if (session_cache_timeout < 0 ||
2414 session_cache_timeout > INT_MAX) {
2415 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 36,
2416 "Invalid session_cache_timeout parameter value.",
2417 __FILE__, __LINE__);
2421 session_cache_mode = SSL_SESS_CACHE_OFF;
2424 //// SSL handshake timer parameter
2425 // Get parameter "timeout_sec".
2426 handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2430 if (unlikely(err)) {
2431 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2432 "timeout_sec parameter not found. Use default value.", __FILE__, __LINE__);
2433 handshake_timeout = DEFAULT_SSL_HANDSHAKE_TIMEOUT;
2434 } else if (handshake_timeout <= 0 || handshake_timeout > INT_MAX) {
2435 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 37,
2436 "Invalid timeout_sec parameter value.", __FILE__, __LINE__);
2446 //*-------- DEBUG LOG --------*/
2447 if (unlikely(LOG_LV_DEBUG ==
2448 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2449 std::stringstream buf;
2450 buf << "out_function: bool virtualservice_tcp::get_ssl_parameter(): ";
2451 buf << "ca_dir = " << ca_dir << ", ";
2452 buf << "ca_file = " << ca_file << ", ";
2453 buf << "cert_chain_dir = " << cert_chain_dir << ", ";
2454 buf << "cert_chain_file = " << cert_chain_file << ", ";
2455 buf << "private_key_dir = " << private_key_dir << ", ";
2456 buf << "private_key_file = " << private_key_file << ", ";
2457 buf << "private_key_filetype = " << private_key_filetype << ", ";
2458 buf << "private_key_passwd_dir = " << private_key_passwd_dir << ", ";
2459 buf << "private_key_passwd_file = " << private_key_passwd_file << ", ";
2460 buf << "verify_options = " << verify_options << ", ";
2461 buf << "verify_cert_depth = " << verify_cert_depth << ", ";
2462 buf << "ssl_options = " << ssl_options << ", ";
2463 if (is_tmp_dh_use) {
2464 buf << "tmp_dh_dir = " << tmp_dh_dir << ", ";
2465 buf << "tmp_dh_file = " << tmp_dh_file << ", ";
2467 buf << "cipher_list = " << cipher_list << ", ";
2468 buf << "session_cache_mode = " << session_cache_mode << ", ";
2469 if (is_session_cache_use) {
2470 buf << "session_cache_size = " << session_cache_size << ", ";
2471 buf << "session_cache_timeout = " << session_cache_timeout << ", ";
2473 buf << "handshake_timeout = " << handshake_timeout;
2474 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2476 __FILE__, __LINE__);
2478 //*------ DEBUG LOG END ------*/
2483 // set ssl context and ssl session cache configuration
2484 // @return set ssl config result
2485 bool l7vs::virtualservice_tcp::set_ssl_config()
2487 //*-------- DEBUG LOG --------*/
2488 if (unlikely(LOG_LV_DEBUG ==
2489 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2490 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 106,
2491 "in_function: bool virtualservice_tcp::set_ssl_config()",
2492 __FILE__, __LINE__);
2494 //*------ DEBUG LOG END ------*/
2496 bool retbool = false;
2499 //// SSL context setting.
2501 if (ca_file.size() == 0) {
2502 // specified CA path.
2504 sslcontext.add_verify_path(ca_dir);
2505 } catch (std::exception &e) {
2506 std::stringstream buf;
2507 buf << "Set root CA path error: " << e.what() << ".";
2508 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2510 __FILE__, __LINE__);
2514 // specified CA file.
2516 sslcontext.load_verify_file(ca_dir + ca_file);
2517 } catch (std::exception &e) {
2518 std::stringstream buf;
2519 buf << "Set root CA file error: " << e.what() << ".";
2520 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2522 __FILE__, __LINE__);
2527 // Set certificate chain file.
2529 sslcontext.use_certificate_chain_file(
2530 cert_chain_dir + cert_chain_file);
2531 } catch (std::exception &e) {
2532 std::stringstream buf;
2533 buf << "Set certificate chain file error: " << e.what() << ".";
2534 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2535 __FILE__, __LINE__);
2539 // Set password callback function.
2541 sslcontext.set_password_callback(
2542 boost::bind(&virtualservice_tcp::get_ssl_password, this));
2543 } catch (std::exception &e) {
2544 std::stringstream buf;
2545 buf << "Set password callback error: " << e.what() << ".";
2546 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2547 __FILE__, __LINE__);
2551 // Set private key file and filetype.
2553 sslcontext.use_private_key_file(
2554 private_key_dir + private_key_file, private_key_filetype);
2555 } catch (std::exception &e) {
2556 std::stringstream buf;
2557 buf << "Set private key file and filetype error: " << e.what() << ".";
2558 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2559 __FILE__, __LINE__);
2563 // Set verify options on the context.
2565 sslcontext.set_verify_mode(verify_options);
2566 } catch (std::exception &e) {
2567 std::stringstream buf;
2568 buf << "Set verify option error: " << e.what() << ".";
2569 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2570 __FILE__, __LINE__);
2574 // Set verify depth on the context.
2575 SSL_CTX_set_verify_depth(sslcontext.impl(), verify_cert_depth);
2577 // Set SSL options on the context.
2579 sslcontext.set_options(ssl_options);
2580 } catch (std::exception &e) {
2581 std::stringstream buf;
2582 buf << "Set SSL option error: " << e.what() << ".";
2583 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999, buf.str(),
2584 __FILE__, __LINE__);
2588 // Set temporary Diffie-Hellman parameters file.
2589 if (is_tmp_dh_use) {
2591 sslcontext.use_tmp_dh_file(tmp_dh_dir + tmp_dh_file);
2592 } catch (std::exception &e) {
2593 std::stringstream buf;
2594 buf << "Set tmp DH file error: " << e.what() << ".";
2595 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2597 __FILE__, __LINE__);
2603 // Set cipher list on the context.
2604 if (unlikely(SSL_CTX_set_cipher_list(sslcontext.impl(),
2605 cipher_list.c_str()) != 1)) {
2606 std::stringstream buf;
2607 buf << "Set cipher list error.";
2608 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2610 __FILE__, __LINE__);
2614 //// SSL session cache setting.
2615 if (is_session_cache_use) {
2616 // Set session id context on the context.
2617 if (unlikely(SSL_CTX_set_session_id_context(
2619 (const unsigned char *)"ultramonkey", 11) != 1)) {
2620 std::stringstream buf;
2621 buf << "Set session id context error.";
2622 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, /*FIXME*/999,
2624 __FILE__, __LINE__);
2628 // Set session cache mode on the context.
2629 SSL_CTX_set_session_cache_mode(
2630 sslcontext.impl(), session_cache_mode);
2632 // Set session cache size on the context.
2633 SSL_CTX_sess_set_cache_size(sslcontext.impl(), session_cache_size);
2635 // Set session cache timeout on the context.
2636 SSL_CTX_set_timeout(sslcontext.impl(), session_cache_timeout);
2639 // session cache OFF.
2640 SSL_CTX_set_session_cache_mode(sslcontext.impl(),
2641 SSL_SESS_CACHE_OFF);
2649 //*-------- DEBUG LOG --------*/
2650 if (unlikely(LOG_LV_DEBUG ==
2651 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2652 std::stringstream buf;
2653 buf << "out_function: bool virtualservice_tcp::set_ssl_config(): ";
2654 get_ssl_config(buf);
2655 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 117, buf.str(),
2656 __FILE__, __LINE__);
2658 //*------ DEBUG LOG END ------*/
2663 // flush ssl session
2664 void l7vs::virtualservice_tcp::flush_ssl_session()
2666 // check expired cached sessions and do flushing
2667 // Need ssl_context lock?
2668 SSL_CTX_flush_sessions(sslcontext.impl(), time(0));
2672 // get ssl configuration form ssl context. (for debug)
2673 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream &buf)
2675 buf << "SSL configuration information: ";
2676 buf << "Verify mode[" << SSL_CTX_get_verify_mode(sslcontext.impl()) << "] ";
2677 buf << "Verify depth[" << SSL_CTX_get_verify_depth(sslcontext.impl()) << "] ";
2678 buf << "SSL options[" << SSL_CTX_get_options(sslcontext.impl()) << "] ";
2679 buf << "Cache mode[" << SSL_CTX_get_session_cache_mode(sslcontext.impl()) << "] ";
2680 buf << "Cache size[" << SSL_CTX_sess_get_cache_size(sslcontext.impl()) << "] ";
2681 buf << "Cache timeout[" << SSL_CTX_get_timeout(sslcontext.impl()) << "] ";
2685 // get ssl session cache information form ssl context. (for debug)
2686 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream &buf)
2688 buf << "SSL session cache information: ";
2689 buf << "Session number[" << SSL_CTX_sess_number(sslcontext.impl()) << "] ";
2690 buf << "Accept[" << SSL_CTX_sess_accept(sslcontext.impl()) << "] ";
2691 buf << "Accept good[" << SSL_CTX_sess_accept_good(sslcontext.impl()) << "] ";
2692 buf << "Accept renegotiate[" << SSL_CTX_sess_accept_renegotiate(sslcontext.impl()) << "] ";
2693 buf << "Hits[" << SSL_CTX_sess_hits(sslcontext.impl()) << "] ";
2694 buf << "Misses[" << SSL_CTX_sess_misses(sslcontext.impl()) << "] ";
2695 buf << "Timeouts[" << SSL_CTX_sess_timeouts(sslcontext.impl()) << "] ";
2696 buf << "Cache full[" << SSL_CTX_sess_cache_full(sslcontext.impl()) << "] ";