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>
32 #include "virtualservice.h"
33 #include "logger_enum.h"
35 #include "parameter.h"
39 #include "logger_access_manager.h"
41 // imprementation 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("")
61 private_key_file = "";
62 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
63 private_key_passwd_dir = "";
64 private_key_passwd_file = "";
66 verify_cert_depth = 0;
68 is_tmp_dh_use = false;
72 is_session_cache_use = false;
73 session_cache_mode = 0;
74 session_cache_size = 0;
75 session_cache_timeout = 0;
76 handshake_timeout = 0;
80 * virtualservice_tcp class destructor.
82 l7vs::virtualservice_tcp::~virtualservice_tcp(){
86 * replication interrupt event
91 void l7vs::virtualservice_tcp::handle_replication_interrupt( const boost::system::error_code& err ){
92 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
93 boost::format fmt("in_function : void virtualservice_tcp::handle_replication_interrupt( "
94 "const boost::system::error_code& err ) : err = %s, err.message = %s");
95 fmt % ( err ? "true" : "false") % err.message();
96 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 20, fmt.str(), __FILE__, __LINE__ );
99 if( unlikely( err ) ){
101 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, err.message(), __FILE__, __LINE__ );
106 replication& rep_noconst = const_cast<replication&>( rep );
108 if( replication::REPLICATION_SINGLE == rep_noconst.get_status() ){
109 Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "replication mode is single.", __FILE__, __LINE__ );
113 std::stringstream tmp_tcp_ep;
114 tmp_tcp_ep << element.tcp_accept_endpoint;
115 std::stringstream tmp_udp_ep;
116 tmp_udp_ep << element.udp_recv_endpoint;
117 std::stringstream tmp_sorry_ep;
118 tmp_sorry_ep << element.sorry_endpoint;
120 //get replication area
121 unsigned int rep_size = 0;
122 replication_header* rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
123 if( (rep_header_ptr == NULL) || (0 == rep_size) ){
124 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
129 if( ( rep_size * DATA_SIZE ) <
130 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
131 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
135 //lock replication area
136 rep_noconst.lock( REP_AREA_NAME );
138 //read header value and set loop count
139 unsigned int loop_cnt = rep_header_ptr->data_num;
140 //if data_num over MAX_REPLICATION_DATA_NUM, data_num = 0
141 if( static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt )
144 //set start pointer(pointer of replication_data)
145 replication_data* rep_data_ptr = reinterpret_cast<replication_data*>( ++rep_header_ptr );
148 for( unsigned int i = 0; i < loop_cnt; ++i ){
149 //check equal udpmode and tcp_accept_endpoint
150 if( (rep_data_ptr->udpmode == element.udpmode )&&
151 ( 0 == strncmp( rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 47 ) ) ){
155 //increment data pointer
159 //if it is new data, increment data num.
161 rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
162 ++(rep_header_ptr->data_num);
164 //write replication data
165 rep_data_ptr->udpmode = element.udpmode;
166 strncpy( rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 48 );
167 strncpy( rep_data_ptr->udp_endpoint, tmp_udp_ep.str().c_str(), 48 );
168 rep_data_ptr->sorry_maxconnection = element.sorry_maxconnection;
169 strncpy( rep_data_ptr->sorry_endpoint, tmp_sorry_ep.str().c_str(), 48 );
170 rep_data_ptr->sorry_flag = element.sorry_flag;
171 rep_data_ptr->qos_up = element.qos_upstream;
172 rep_data_ptr->qos_down = element.qos_downstream;
174 //unlock replication area
175 rep_noconst.unlock( REP_AREA_NAME );
177 //register handle_replication_interrupt
178 replication_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
179 replication_timer->async_wait( boost::bind( &virtualservice_tcp::handle_replication_interrupt,
180 this, boost::asio::placeholders::error ) );
182 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
183 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 21, "out_function : void virtualservice_tcp::handle_replication_interrupt( const boost::system::error_code& err )", __FILE__, __LINE__ );
188 * read replication data
190 * @param read_replicationdata
194 void l7vs::virtualservice_tcp::read_replicationdata(){
195 Logger funclog( LOG_CAT_L7VSD_VIRTUALSERVICE, 22, "function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
197 replication& rep_noconst = const_cast<replication&>( rep );
199 if( replication::REPLICATION_SINGLE == rep_noconst.get_status() ){
200 Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, "replication mode is single.", __FILE__, __LINE__ );
204 unsigned int rep_size = 0;
205 replication_header* rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
206 if( (rep_header_ptr == NULL) || (0 == rep_size) ){
207 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 3, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
208 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
209 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 23, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
215 if( ( rep_size * DATA_SIZE ) <
216 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
217 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 4, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
218 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
219 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 24, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
223 //lock replication area
224 rep_noconst.lock( REP_AREA_NAME );
226 //read header value and set loop count
227 unsigned int loop_cnt = rep_header_ptr->data_num;
228 //if data_num over MAX_REPLICATION_DATA_NUM, set data_num = 0
229 if( static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt ){
230 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 5, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
231 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
232 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 25, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
234 rep_header_ptr->data_num = 0;
235 rep_noconst.unlock( REP_AREA_NAME );
239 //set start pointer(pointer of replication_data)
240 replication_data* rep_data_ptr = reinterpret_cast<replication_data*>( ++rep_header_ptr );
243 for( unsigned int i = 0; i < loop_cnt; ++i ){
244 //get tcp endpointdata
245 std::string tmpstr = rep_data_ptr->tcp_endpoint;
247 unsigned short portno;
249 portno = boost::lexical_cast<unsigned short>( tmpstr.substr( (tmpstr.rfind( ":" )+1) ) );
251 catch( const boost::bad_lexical_cast& err ){
254 if( tmpstr[0] == '[' ){
256 ipaddr = tmpstr.substr( 1, (tmpstr.rfind( "]" )-1) );
259 ipaddr = tmpstr.substr( 0, tmpstr.rfind( ":" ) );
261 //check equal udpmode and tcp_accept_endpoint
262 if( (rep_data_ptr->udpmode == element.udpmode )&&
263 ( tcp_endpoint_type( boost::asio::ip::address::from_string( ipaddr ), portno ) == element.tcp_accept_endpoint ) ){
264 element.sorry_maxconnection = rep_data_ptr->sorry_maxconnection;
265 tmpstr = rep_data_ptr->sorry_endpoint;
267 portno = boost::lexical_cast<unsigned short>( tmpstr.substr( (tmpstr.rfind( ":" )+1) ) );
269 catch( const boost::bad_lexical_cast& err ){
272 if( tmpstr[0] == '[' ){
274 ipaddr = tmpstr.substr( 1, (tmpstr.rfind( "]" )-1) );
277 ipaddr = tmpstr.substr( 0, tmpstr.rfind( ":" ) );
279 element.sorry_endpoint =
280 tcp_endpoint_type( boost::asio::ip::address::from_string( ipaddr ), portno );
281 element.sorry_flag = rep_data_ptr->sorry_flag;
282 element.qos_upstream = rep_data_ptr->qos_up;
283 element.qos_downstream = rep_data_ptr->qos_down;
286 //increment data pointer
290 //unlock replication area
291 rep_noconst.unlock( REP_AREA_NAME );
293 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
294 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 26, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
301 * @param handle_accept
305 void l7vs::virtualservice_tcp::handle_accept( const l7vs::session_thread_control* stc_ptr, const boost::system::error_code& err ){
306 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
307 boost::format funclog_fmt("in_function : void virtualservice_tcp::handle_accept( "
308 "const boost::shared_ptr<session_thread_control> , "
309 "const boost::system::error_code& err ) : err = %s, err.message = %s");
310 funclog_fmt % ( err ? "true" : "false") % err.message();
311 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 27, funclog_fmt.str(), __FILE__, __LINE__ );
314 session_thread_control* stc_ptr_noconst = const_cast<session_thread_control*>( stc_ptr );
316 if( unlikely( err ) ){
318 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, err.message(), __FILE__, __LINE__ );
322 tcp_session* tmp_session = stc_ptr_noconst->get_session().get();
324 // ssl session cache flush
325 if( ( ssl_file_name != "" ) && ( is_session_cache_use == true ) ) {
327 //*-------- DEBUG LOG --------*/
328 if (unlikely(LOG_LV_DEBUG ==
329 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
330 std::stringstream buf;
331 buf << "virtualservice_tcp::handle_accept() : ";
332 buf << "ssl session cache flush before : ";
333 get_ssl_session_cache_info(buf);
334 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
336 __FILE__, __LINE__ );
338 //*------ DEBUG LOG END ------*/
340 long ssl_cache_num = SSL_CTX_sess_number(sslcontext.impl());
341 if ( ssl_cache_num >= session_cache_size ) {
345 //*-------- DEBUG LOG --------*/
346 if (unlikely(LOG_LV_DEBUG ==
347 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
348 std::stringstream buf;
349 buf << "virtualservice_tcp::handle_accept() : ";
350 buf << "ssl session cache flush after : ";
351 get_ssl_session_cache_info(buf);
352 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
354 __FILE__, __LINE__ );
356 //*------ DEBUG LOG END ------*/
360 // send access log output ON or OFF message to tcp_session
361 stc_ptr_noconst->session_access_log_output_mode_change( access_log_flag );
363 active_sessions.insert( tmp_session, stc_ptr_noconst );
365 //check sorry flag and status
366 if ( unlikely( ( 0 != element.sorry_flag ) ||
367 ( ( 0 < element.sorry_maxconnection ) &&
368 ( ( active_count.get() >= static_cast<size_t>( element.sorry_maxconnection ) ) ) ) ) ){
369 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
370 boost::format fmt( "Connection switch Sorry mode. : active_session.size = %d / active_count.get = %d" );
371 fmt % active_sessions.size() % active_count.get();
372 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 30, fmt.str(), __FILE__, __LINE__ );
374 stc_ptr_noconst->get_session()->set_virtual_service_message( tcp_session::SORRY_STATE_ENABLE );
377 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
378 boost::format fmt1( "active session thread id = %d" );
379 fmt1 % stc_ptr_noconst->get_upthread_id();
380 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 31, fmt1.str(), __FILE__, __LINE__ );
381 boost::format fmt2( "pool_session.size = %d" );
382 fmt2 % pool_sessions.size();
383 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 32, fmt2.str(), __FILE__, __LINE__ );
384 boost::format fmt3( "active_session.size = %d" );
385 fmt3 % active_sessions.size();
386 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 33, fmt3.str(), __FILE__, __LINE__ );
387 boost::format fmt4( "active_count = %d" );
388 fmt4 % active_count.get();
389 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 34, fmt4.str(), __FILE__, __LINE__ );
392 session_thread_control* tmp_stc_ptr = waiting_sessions.find( stc_ptr_noconst->get_session().get() );
393 waiting_sessions.erase( tmp_stc_ptr->get_session().get() );
395 stc_ptr_noconst->startupstream();
396 stc_ptr_noconst->startdownstream();
398 //waiting, pool_sessions.size become over 1
399 //pick up session from pool
400 session_thread_control* stc_ptr_register_accept;
402 stc_ptr_register_accept = pool_sessions.pop();
404 while( unlikely( !stc_ptr_register_accept ) );
406 //session add wait_sessions
407 boost::mutex::scoped_lock up_wait_lk( stc_ptr_register_accept->get_upthread_mutex() );
408 boost::mutex::scoped_lock down_wait_lk( stc_ptr_register_accept->get_downthread_mutex() );
410 waiting_sessions.insert( stc_ptr_register_accept->get_session().get(), stc_ptr_register_accept );
412 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
413 boost::format fmt1( "active session thread id = %d" );
414 fmt1 % stc_ptr_register_accept->get_upthread_id();
415 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 35, fmt1.str(), __FILE__, __LINE__ );
416 boost::format fmt2( "pool_session.size = %d" );
417 fmt2 % pool_sessions.size();
418 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 36, fmt2.str(), __FILE__, __LINE__ );
419 boost::format fmt3( "active_session.size = %d" );
420 fmt3 % active_sessions.size();
421 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 37, fmt3.str(), __FILE__, __LINE__ );
422 boost::format fmt4( "active_count = %d" );
423 fmt4 % active_count.get();
424 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 38, fmt4.str(), __FILE__, __LINE__ );
427 //regist accept event handler
428 if (!ssl_virtualservice_mode_flag) {
429 acceptor_.async_accept( stc_ptr_register_accept->get_session()->get_client_socket(),
430 boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr_register_accept, boost::asio::placeholders::error ) );
432 acceptor_.async_accept( stc_ptr_register_accept->get_session()->get_client_ssl_socket().lowest_layer(),
433 boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr_register_accept, boost::asio::placeholders::error ) );
436 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
437 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 39, "out_function : void virtualservice_tcp::handle_accept( const boost::shared_ptr<session_thread_control> , const boost::system::error_code& err )", __FILE__, __LINE__ );
442 * initialize virtualservice(TCP)
447 void l7vs::virtualservice_tcp::initialize( l7vs::error_code& err ){
448 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
449 boost::format formatter("in_function : void virtualservice_tcp::initialize( "
450 "l7vs::error_code& err )");
451 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 40, formatter.str(), __FILE__, __LINE__ );
453 if( pool_sessions.size() != 0 ){
454 err.setter( true, "VirtualService already initialized." );
455 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
456 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
457 "l7vs::error_code& err ) : err = %s, err.message = %s");
458 formatter % ( err ? "true" : "false") % err.get_message();
459 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 41, formatter.str(), __FILE__, __LINE__ );
464 //load parameter value
465 load_parameter( err );
467 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
468 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
469 "l7vs::error_code& err ) : err = %s, err.message = %s");
470 formatter % ( err ? "true" : "false") % err.get_message();
471 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 42, formatter.str(), __FILE__, __LINE__ );
476 // access log flag and access log file name setting contents check.
477 if( element.access_log_flag == 1 && element.access_log_file_name == "" ) {
478 boost::format formatter("access log file name not set error");
479 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 3, formatter.str(), __FILE__, __LINE__ );
480 err.setter( true, "access log file name not set error" );
484 logger_implement_access *access_log_instance = NULL;
485 // access log instance create.
486 if( element.access_log_file_name != "" ) {
488 = logger_access_manager::getInstance().find_logger_implement_access(
489 element.access_log_file_name,
490 element.access_log_rotate_arguments,
492 if( access_log_instance == NULL ) {
493 boost::format formatter("access logger Instance acquisition err = %s, err.message = %s ");
494 formatter % ( err ? "true" : "false") % err.get_message();
495 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 4, formatter.str(), __FILE__, __LINE__ );
496 err.setter( true, "access log class instance create failed" );
502 boost::asio::ip::address address = element.tcp_accept_endpoint.address();
503 #ifdef SCHED_SETAFFINITY
504 vsnic_cpumask = get_cpu_mask( address );
505 rsnic_cpumask = get_cpu_mask( param_data.nic_realserver_side );
509 boost::system::error_code acceptor_err;
510 acceptor_.open( element.tcp_accept_endpoint.protocol(), acceptor_err );
512 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 5, acceptor_err.message(), __FILE__, __LINE__ );
513 err.setter( true, acceptor_err.message() );
516 acceptor_.set_option( boost::asio::ip::tcp::acceptor::reuse_address( true ), acceptor_err );
518 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 6, acceptor_err.message(), __FILE__, __LINE__ );
519 err.setter( true, acceptor_err.message() );
522 if( likely(address.is_v6()) ) {
523 boost::asio::ip::v6_only option(true);
524 acceptor_.set_option( option, acceptor_err );
526 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 7, acceptor_err.message(), __FILE__, __LINE__ );
527 err.setter( true, acceptor_err.message() );
531 acceptor_.bind( element.tcp_accept_endpoint, acceptor_err );
533 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 8, acceptor_err.message(), __FILE__, __LINE__ );
534 err.setter( true, acceptor_err.message() );
538 //read replication data
539 read_replicationdata();
541 //load protocol module
542 protomod = protocol_module_control::getInstance().load_module( element.protocol_module_name );
543 if( NULL == protomod ){
545 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 9, PROTOMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
546 err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
547 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
548 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
549 "l7vs::error_code& err ) : err = %s, err.message = %s");
550 formatter % ( err ? "true" : "false") % err.get_message();
551 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 43, formatter.str(), __FILE__, __LINE__ );
555 //Protocol Module Initialize
556 protomod->init_logger_functions(
557 boost::bind( &Logger::getLogLevel, LOG_CAT_PROTOCOL ),
558 boost::bind( &Logger::putLogFatal, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
559 boost::bind( &Logger::putLogError, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
560 boost::bind( &Logger::putLogWarn, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
561 boost::bind( &Logger::putLogInfo, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
562 boost::bind( &Logger::putLogDebug, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ) );
563 protomod->initialize(
564 boost::bind( &virtualservice_tcp::rs_list_begin, this ),
565 boost::bind( &virtualservice_tcp::rs_list_end, this ),
566 boost::bind( &virtualservice_tcp::rs_list_next, this, _1 ),
567 boost::bind( &virtualservice_tcp::rs_list_lock, this ),
568 boost::bind( &virtualservice_tcp::rs_list_unlock, this ) );
569 protomod->init_replication_functions(
570 boost::bind( &virtualservice_tcp::replication_pay_memory, this, _1, _2 ),
571 boost::bind( &virtualservice_tcp::replication_area_lock, this, element.protocol_module_name ),
572 boost::bind( &virtualservice_tcp::replication_area_unlock, this, element.protocol_module_name ),
573 element.tcp_accept_endpoint,
574 element.udp_recv_endpoint );
575 tcp_schedule_func_type sched_rs_func = boost::bind( &virtualservice_tcp::schedule_rs, this, _1, _2, _3, _4, _5 );
576 protomod->register_schedule( sched_rs_func );
578 protocol_module_base::check_message_result pm_result;
580 pm_result = protomod->check_parameter( element.protocol_args );
581 if( !pm_result.flag ){
582 err.setter( true, "Protocol Module argument error." );
583 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
584 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
585 "l7vs::error_code& err ) : err = %s, err.message = %s");
586 formatter % ( err ? "true" : "false") % err.get_message();
587 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 44, formatter.str(), __FILE__, __LINE__ );
591 pm_result = protomod->set_parameter( element.protocol_args );
592 if( !pm_result.flag ){
593 err.setter( true, "Protocol Module argument error." );
594 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
595 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
596 "l7vs::error_code& err ) : err = %s, err.message = %s");
597 formatter % ( err ? "true" : "false") % err.get_message();
598 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 45, formatter.str(), __FILE__, __LINE__ );
603 protomod->get_option_info(protocol_module_for_indication_options);
604 element.protocol_module_for_indication_options = protocol_module_for_indication_options;
606 //load schedule module
607 schedmod = schedule_module_control::getInstance().load_module( element.schedule_module_name );
608 if( NULL == schedmod ){
610 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 10, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
611 err.setter( true, SCHEDMOD_LOAD_ERROR_MSG );
612 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
613 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
614 "l7vs::error_code& err ) : err = %s, err.message = %s");
615 formatter % ( err ? "true" : "false") % err.get_message();
616 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 46, formatter.str(), __FILE__, __LINE__ );
620 //Schedule Module Initialize
621 schedmod->init_logger_functions(
622 boost::bind( &Logger::getLogLevel, LOG_CAT_SCHEDULE ),
623 boost::bind( &Logger::putLogFatal, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
624 boost::bind( &Logger::putLogError, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
625 boost::bind( &Logger::putLogWarn, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
626 boost::bind( &Logger::putLogInfo, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
627 boost::bind( &Logger::putLogDebug, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ) );
628 schedmod->initialize();
629 schedmod->init_replication_functions(
630 boost::bind( &virtualservice_tcp::replication_pay_memory, this, _1, _2 ),
631 boost::bind( &virtualservice_tcp::replication_area_lock, this, element.schedule_module_name ),
632 boost::bind( &virtualservice_tcp::replication_area_unlock, this, element.schedule_module_name ),
633 element.tcp_accept_endpoint,
634 element.udp_recv_endpoint );
636 // access log flag set
637 access_log_flag = false;
638 if ( element.access_log_flag == 1 ) {
639 access_log_flag = true;
642 // access log rotation infomation set.
643 if ( element.access_log_rotate_key_info == "" ) {
644 element.access_log_rotate_key_info = "none";
645 element.access_log_rotate_verbose_info = logger_access_manager::getInstance().get_rotate_default_verbose_displayed_contents();
647 element.access_log_rotate_verbose_info = element.access_log_rotate_key_info;
649 access_log_file_name = element.access_log_file_name;
650 access_log_rotate_arguments = element.access_log_rotate_arguments;
653 ssl_virtualservice_mode_flag = false;
654 ssl_file_name = element.ssl_file_name;
655 if ( ssl_file_name != "" ) {
656 ssl_file_name = element.ssl_file_name;
658 if(unlikely(!get_ssl_parameter())) {
660 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 11, "get ssl parameter failed", __FILE__, __LINE__ );
661 err.setter( true, "get ssl parameter failed" );
664 // set SSL configuration
665 if(unlikely(!set_ssl_config())) {
667 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 12, "set ssl config failed", __FILE__, __LINE__ );
668 err.setter( true, "set ssl config failed" );
671 ssl_virtualservice_mode_flag = true;
677 //create session pool
679 for( int i = 0; i < param_data.session_pool_size; ++i ){
681 tcp_session* sess = new tcp_session(*this,
684 element.tcp_accept_endpoint,
685 ssl_virtualservice_mode_flag,
687 is_session_cache_use,
689 access_log_instance);
690 session_result_message result = sess->initialize();
691 if( result.flag == true ){
692 err.setter( result.flag, result.message );
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, 47, formatter.str(), __FILE__, __LINE__ );
701 session_thread_control* p_stc = new session_thread_control( sess, vsnic_cpumask, rsnic_cpumask, -1 );
702 while( !pool_sessions.push( p_stc ) ){}
704 catch( std::bad_alloc ex ){
706 LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "error, create session.", __FILE__, __LINE__ );
707 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
708 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
709 "l7vs::error_code& err ) : err = %s, err.message = %s");
710 formatter % ( err ? "true" : "false") % err.get_message();
711 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 48, formatter.str(), __FILE__, __LINE__ );
716 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
717 boost::format fmt1( "pool_session.size = %d" );
718 fmt1 % pool_sessions.size();
719 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 49, fmt1.str(), __FILE__, __LINE__ );
720 boost::format fmt2( "active_session.size = %d" );
721 fmt2 % active_sessions.size();
722 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 50, fmt2.str(), __FILE__, __LINE__ );
726 err.setter( false, "" );
728 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
729 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
730 "l7vs::error_code& err ) : err = %s, err.message = %s");
731 formatter % ( err ? "true" : "false") % err.get_message();
732 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 51, formatter.str(), __FILE__, __LINE__ );
737 * finalize virtualservice(TCP)
742 void l7vs::virtualservice_tcp::finalize( l7vs::error_code& err ){
743 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
744 boost::format formatter("in_function : void virtualservice_tcp::finalize( "
745 "l7vs::error_code& err )");
746 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 52, formatter.str(), __FILE__, __LINE__ );
748 boost::format fmt1( "pool_session.size = %d" );
749 fmt1 % pool_sessions.size();
750 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 53, fmt1.str(), __FILE__, __LINE__ );
751 boost::format fmt2( "active_session.size = %d" );
752 fmt2 % active_sessions.size();
753 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 54, fmt2.str(), __FILE__, __LINE__ );
759 while(active_sessions.size()){
760 boost::this_thread::yield();
764 tcp_session* tmp_session = NULL;
765 session_thread_control* tmp_stc = NULL;
766 waiting_sessions.pop( tmp_session, tmp_stc );
771 if( likely( pool_sessions.push( tmp_stc ) ) )break;
775 //release sessions[i]->join();
776 while( !pool_sessions.empty() ){
777 session_thread_control* stc = pool_sessions.pop();
780 boost::mutex::scoped_lock upthread_wait( stc->get_upthread_mutex() );
781 boost::mutex::scoped_lock downthread_wait( stc->get_downthread_mutex() );
785 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
786 boost::format fmt( "join pool sessin : pool_sessions.size = %d" );
787 fmt % pool_sessions.size();
788 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 55, fmt.str(), __FILE__, __LINE__ );
792 //unload ProtocolModule
794 //finalize ProtocolModule
795 protomod->finalize();
796 //unload ProtocolModule
797 protocol_module_control::getInstance().unload_module( protomod );
800 //unload ScheduleModule
802 schedule_module_control::getInstance().unload_module( schedmod );
806 active_sessions.clear();
807 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
808 boost::format fmt1( "pool_session.size = %d" );
809 fmt1 % pool_sessions.size();
810 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 56, fmt1.str(), __FILE__, __LINE__ );
811 boost::format fmt2( "active_session.size = %d" );
812 fmt2 % active_sessions.size();
813 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 57, fmt2.str(), __FILE__, __LINE__ );
816 //clear replication_data
817 bool replication_status = true;
818 replication& rep_noconst = const_cast<replication&>( rep );
820 if( replication::REPLICATION_SINGLE != rep_noconst.get_status() ){
821 unsigned int rep_size = 0;
822 replication_header* rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
823 if( (rep_header_ptr == NULL) || (0 == rep_size) ){
824 err.setter( true, REP_BLOCK_SIZE_ERR_MSG );
825 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 6, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
826 replication_status = false;
830 if( ( rep_size * DATA_SIZE ) <
831 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
832 err.setter( true, REP_AREA_SIZE_ERR_MSG );
833 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 7, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
834 replication_status = false;
836 if( (NULL != rep_header_ptr) && (replication_status) ){
837 //lock replication area
838 rep_noconst.lock( REP_AREA_NAME );
840 rep_header_ptr->data_num = 0;
841 //unlock replication area
842 rep_noconst.unlock( REP_AREA_NAME );
846 vsd.release_virtual_service( element );
848 if( access_log_file_name != "" ) {
849 // erase access log instance.
850 logger_access_manager::getInstance().erase_logger_implement_access( access_log_file_name, err );
851 if ( unlikely(err) ) {
852 boost::format fmt( "access logger instance erase err:%s" );
853 fmt % err.get_message();
854 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 8,
856 __FILE__, __LINE__ );
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::finalize( "
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, 58, formatter.str(), __FILE__, __LINE__ );
872 * equal compare virtualservice(TCP)
874 * @param virtualservice_base
875 * @return bool ( true = equal )
877 bool l7vs::virtualservice_tcp::operator==( const l7vs::virtualservice_base& in ){
878 boost::format formatter("function : void virtualservice_tcp::operator==( "
879 "const l7vs::virtualservice_base& in )");
880 Logger funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 59, formatter.str(), __FILE__, __LINE__ );
882 virtualservice_base& vs = const_cast<virtualservice_base&>( in );
883 return ( ( element.tcp_accept_endpoint == vs.get_element().tcp_accept_endpoint )
884 && ( element.udpmode == vs.get_element().udpmode ) );
888 * not-equal compare virtualservice(TCP)
890 * @param virtualservice_base
891 * @return bool ( true = not-equal )
893 bool l7vs::virtualservice_tcp::operator!=( const l7vs::virtualservice_base& in ){
894 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
895 boost::format formatter("in/out_function : void virtualservice_tcp::operator!=( "
896 "const l7vs::virtualservice_base& in )");
897 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 60, formatter.str(), __FILE__, __LINE__ );
899 virtualservice_base& vs = const_cast<virtualservice_base&>( in );
900 return ( ( element.tcp_accept_endpoint != vs.get_element().tcp_accept_endpoint )
901 || ( element.udpmode != vs.get_element().udpmode ) );
905 * add VirtualService( not-imprement )
907 * @param virtualservice_element
911 void l7vs::virtualservice_tcp::set_virtualservice( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
912 err.setter( false, "" );
916 * edit VirtualService
918 * @param virtualservice_element
922 void l7vs::virtualservice_tcp::edit_virtualservice( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
923 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
924 boost::format formatter("in_function : void virtualservice_tcp::edit_virtualservice( "
925 "const l7vs::virtualservice_element& in,"
926 "l7vs::error_code& err ) : dump in ");
927 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 61, formatter.str(), __FILE__, __LINE__ );
930 virtualservice_element& elem = const_cast<virtualservice_element&>( in );
931 //郢昜サ」ホ帷ケ晢ス。郢晢スシ郢ァ・ソ邵コ逾(rtualService邵コ・ォ闕ウツ
\80髢セ・エ邵コ蜷カ・狗クコ蛹コ・、諛域ク言
932 //udpmode邵コ・ィtcp_accept_endpoint邵コ・ィprotocol_module_name邵コ蠕。・クツ
\80髢セ・エ邵コ蜷カ・狗クコ阮吮・
933 if( ( element.udpmode != elem.udpmode ) ||
934 ( element.tcp_accept_endpoint != elem.tcp_accept_endpoint ) ||
935 ( element.protocol_module_name != elem.protocol_module_name ) ){
936 err.setter( true, "Virtual Service does not exist." );
937 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
938 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
939 "const l7vs::virtualservice_element& in,"
940 "l7vs::error_code& err ) : err = %s, err.message = %s");
941 formatter % ( err ? "true" : "false") % err.get_message();
942 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 62, formatter.str(), __FILE__, __LINE__ );
947 //if change ScueduleModule Name, unload old ScheduleModule and load new ScheduleModule
948 if( ( element.schedule_module_name != elem.schedule_module_name ) && ( "" != elem.schedule_module_name ) ){
949 schedule_module_control::getInstance().unload_module( schedmod );
950 schedmod = schedule_module_control::getInstance().load_module( elem.schedule_module_name );
951 if( NULL == schedmod ){
953 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 13, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
954 err.setter( true, SCHEDMOD_LOAD_ERROR_MSG );
955 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
956 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
957 "const l7vs::virtualservice_element& in,"
958 "l7vs::error_code& err ) : err = %s, err.message = %s");
959 formatter % ( err ? "true" : "false") % err.get_message();
960 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 63, formatter.str(), __FILE__, __LINE__ );
964 element.schedule_module_name = elem.schedule_module_name;
967 //additional PM options(for protomod_url)
968 protocol_module_base::check_message_result result;
969 if( NULL != protomod ){
970 result = protomod->add_parameter( elem.protocol_args );
972 for( size_t i = 0; i < elem.protocol_args.size(); ++i ){
973 element.protocol_args.push_back( elem.protocol_args[i] );
976 err.setter( true, result.message );
977 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
978 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
979 "const l7vs::virtualservice_element& in,"
980 "l7vs::error_code& err ) : err = %s, err.message = %s");
981 formatter % ( err ? "true" : "false") % err.get_message();
982 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 64, formatter.str(), __FILE__, __LINE__ );
988 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 14, PROTOMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
989 err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
990 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
991 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
992 "const l7vs::virtualservice_element& in,"
993 "l7vs::error_code& err ) : err = %s, err.message = %s");
994 formatter % ( err ? "true" : "false") % err.get_message();
995 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 65, formatter.str(), __FILE__, __LINE__ );
1002 if( ULLONG_MAX == elem.qos_upstream )
1003 element.qos_upstream = 0ULL;
1004 else if( 0ULL != elem.qos_upstream )
1005 element.qos_upstream = elem.qos_upstream;
1007 if( ULLONG_MAX == elem.qos_downstream )
1008 element.qos_downstream = 0ULL;
1009 else if( 0ULL != elem.qos_downstream )
1010 element.qos_downstream = elem.qos_downstream;
1011 //sorry_maxconnection;
1012 if( LLONG_MAX == elem.sorry_maxconnection )
1013 element.sorry_maxconnection = 0;
1014 else if( 0 != elem.sorry_maxconnection )
1015 element.sorry_maxconnection = elem.sorry_maxconnection;
1017 if( INT_MAX == elem.sorry_flag )
1018 element.sorry_flag = 0;
1019 else if( 0 != elem.sorry_flag )
1020 element.sorry_flag = 1;
1022 //if endpoint of SorryServer equal 255.255.255.255:0,not update
1023 //if equal endpoint 255.255.255.255:0, clear sorry parameters
1024 if( elem.sorry_endpoint ==
1025 boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "255.255.255.255" ), (0)) ){
1026 element.sorry_endpoint = boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "0.0.0.0" ), (0) );
1027 element.sorry_maxconnection = 0LL;
1028 element.sorry_flag = false;
1029 active_sessions.do_all( boost::bind( &session_thread_control::session_sorry_disable, _1 ) );
1031 if( elem.sorry_endpoint !=
1032 boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "0.0.0.0" ), (0) ) )
1033 element.sorry_endpoint = elem.sorry_endpoint;
1035 active_sessions.do_all( boost::bind( &session_thread_control::session_sorry_mode_change, _1, elem.sorry_flag ) );
1038 // access log flag ON and access log filename not set.
1039 if ( elem.access_log_flag == 1 && element.access_log_file_name == "" ) {
1041 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 15, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
1042 err.setter( true, "access log flag change err." );
1046 // access log flag check and send access log output ON or OFF message to tcp_session
1047 element.access_log_flag = elem.access_log_flag;
1048 if (elem.access_log_flag==1 && access_log_flag==false ) {
1049 active_sessions.do_all( boost::bind( &session_thread_control::session_accesslog_output_mode_on, _1 ) );
1050 access_log_flag = true;
1051 } else if ( elem.access_log_flag==0 && access_log_flag==true ) {
1052 active_sessions.do_all( boost::bind( &session_thread_control::session_accesslog_output_mode_off, _1 ) );
1053 access_log_flag = false;
1056 err.setter( false, "" );
1058 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1059 boost::format formatter("out_function : void virtualservice_tcp::set_virtualservice( "
1060 "const l7vs::virtualservice_element& in,"
1061 "l7vs::error_code& err ) : err = %s, err.message = %s");
1062 formatter % ( err ? "true" : "false") % err.get_message();
1063 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 66, formatter.str(), __FILE__, __LINE__ );
1070 * @param virtualservice_element
1074 void l7vs::virtualservice_tcp::add_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1075 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1076 boost::format formatter("in_function : void virtualservice_tcp::add_realserver( "
1077 "const l7vs::virtualservice_element& in,"
1078 "l7vs::error_code& err )");
1079 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 67, formatter.str(), __FILE__, __LINE__ );
1082 virtualservice_element& in_element = const_cast<virtualservice_element&>( in );
1084 //check equal virtualservice
1085 if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1086 err.setter( true, "Virtual Service does not exist." );
1087 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1088 boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
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, 68, formatter.str(), __FILE__, __LINE__ );
1097 if( in.realserver_vector.size() == 0U ){
1098 err.setter( true, "." );
1099 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1100 boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1101 "const l7vs::virtualservice_element& in,"
1102 "l7vs::error_code& err ) : err = %s, err.message = %s");
1103 formatter % ( err ? "true" : "false") % err.get_message();
1104 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 69, formatter.str(), __FILE__, __LINE__ );
1108 //lock rs_list_ref_count_inc_mutex
1109 rw_scoped_lock inc_lock( rs_list_ref_count_inc_mutex );
1111 //waiting, rs_list_ref_count become 0
1112 boost::xtime interval;
1114 boost::condition cond;
1116 interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1117 boost::mutex::scoped_lock lk( mtx );
1118 while( rs_list_ref_count != 0ULL ){
1119 cond.timed_wait( lk, interval );
1122 //check duplication realserver
1123 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1124 itr != in_element.realserver_vector.end();
1126 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1127 rs_itr != rs_list.end(); ++rs_itr ){
1128 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1129 err.setter( true, "Real Server already exist." );
1130 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1131 boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1132 "const l7vs::virtualservice_element& in,"
1133 "l7vs::error_code& err ) : err = %s, err.message = %s");
1134 formatter % ( err ? "true" : "false") % err.get_message();
1135 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 70, formatter.str(), __FILE__, __LINE__ );
1142 //pause active sessions
1143 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1146 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1147 itr != in_element.realserver_vector.end();
1150 rs.tcp_endpoint = itr->tcp_endpoint;
1151 rs.udp_endpoint = itr->udp_endpoint;
1152 rs.weight = itr->weight;
1153 rs_list.push_back( rs );
1156 //run active sessions
1157 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1159 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1160 boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1161 "const l7vs::virtualservice_element& in,"
1162 "l7vs::error_code& err ) : err = %s, err.message = %s");
1163 formatter % ( err ? "true" : "false") % err.get_message();
1164 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 71, formatter.str(), __FILE__, __LINE__ );
1171 * @param virtualservice_element
1175 void l7vs::virtualservice_tcp::edit_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1176 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1177 boost::format formatter("in_function : void virtualservice_tcp::edit_realserver( "
1178 "const l7vs::virtualservice_element& in,"
1179 "l7vs::error_code& err )");
1180 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 72, formatter.str(), __FILE__, __LINE__ );
1182 //check equal virtualservice
1183 if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1184 err.setter( true, "Virtual Service does not exist." );
1185 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1186 boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1187 "const l7vs::virtualservice_element& in,"
1188 "l7vs::error_code& err ) : err = %s, err.message = %s");
1189 formatter % ( err ? "true" : "false") % err.get_message();
1190 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 73, formatter.str(), __FILE__, __LINE__ );
1195 //lock rs_list_ref_count_inc_mutex
1196 rw_scoped_lock inc_lock( rs_list_ref_count_inc_mutex );
1198 //waiting, rs_list_ref_count become 0
1199 boost::xtime interval;
1201 boost::condition cond;
1203 interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1204 boost::mutex::scoped_lock lk( mtx );
1205 while( rs_list_ref_count != 0ULL ){
1206 cond.timed_wait( lk, interval );
1209 virtualservice_element& in_element = const_cast<virtualservice_element&>( in );
1211 //check is exist realserver
1212 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1213 itr != in_element.realserver_vector.end();
1215 bool exist_flag = false;
1216 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1217 rs_itr != rs_list.end(); ++rs_itr ){
1218 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1223 err.setter( true, "Real Server does not exist." );
1224 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1225 boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1226 "const l7vs::virtualservice_element& in,"
1227 "l7vs::error_code& err ) : err = %s, err.message = %s");
1228 formatter % ( err ? "true" : "false") % err.get_message();
1229 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 74, formatter.str(), __FILE__, __LINE__ );
1235 //pause active sessions
1236 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1239 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1240 itr != in_element.realserver_vector.end();
1242 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1243 rs_itr != rs_list.end(); ++rs_itr ){
1244 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1245 rs_itr->udp_endpoint = itr->udp_endpoint;
1247 if( itr->weight != -1 ) {
1248 rs_itr->weight = itr->weight;
1255 //run active sessions
1256 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1258 err.setter( false, "" );
1259 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1260 boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1261 "const l7vs::virtualservice_element& in,"
1262 "l7vs::error_code& err ) : err = %s, err.message = %s");
1263 formatter % ( err ? "true" : "false") % err.get_message();
1264 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 75, formatter.str(), __FILE__, __LINE__ );
1271 * @param virtualservice_element
1275 void l7vs::virtualservice_tcp::del_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1276 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1277 boost::format formatter("in_function : void virtualservice_tcp::del_realserver( "
1278 "const l7vs::virtualservice_element& in,"
1279 "l7vs::error_code& err )");
1280 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 76, formatter.str(), __FILE__, __LINE__ );
1283 //check equal virtualservice
1284 if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1285 err.setter( true, "Virtual Service is not equal." );
1286 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1287 boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1288 "const l7vs::virtualservice_element& in,"
1289 "l7vs::error_code& err ) : err = %s, err.message = %s");
1290 formatter % ( err ? "true" : "false") % err.get_message();
1291 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 77, formatter.str(), __FILE__, __LINE__ );
1296 //lock rs_list_ref_count_inc_mutex
1297 rw_scoped_lock inc_lock( rs_list_ref_count_inc_mutex );
1299 //waiting, rs_list_ref_count become 0
1300 boost::xtime interval;
1302 boost::condition cond;
1304 interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1305 boost::mutex::scoped_lock lk( mtx );
1306 while( rs_list_ref_count != 0ULL ){
1307 cond.timed_wait( lk, interval );
1310 virtualservice_element& in_element = const_cast<virtualservice_element&>( in );
1312 //check is exist realserver
1313 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1314 itr != in_element.realserver_vector.end();
1316 bool exist_flag = false;
1317 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1318 rs_itr != rs_list.end(); ++rs_itr ){
1319 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1324 err.setter( true, "Real Server does not exist." );
1325 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1326 boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1327 "const l7vs::virtualservice_element& in,"
1328 "l7vs::error_code& err ) : err = %s, err.message = %s");
1329 formatter % ( err ? "true" : "false") % err.get_message();
1330 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 78, formatter.str(), __FILE__, __LINE__ );
1336 //pause active sessions
1337 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1340 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1341 itr != in_element.realserver_vector.end();
1343 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1344 rs_itr != rs_list.end(); ++rs_itr ){
1345 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1346 rs_list.erase( rs_itr );
1352 //run active sessions
1353 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1355 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1356 boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1357 "const l7vs::virtualservice_element& in,"
1358 "l7vs::error_code& err ) : err = %s, err.message = %s");
1359 formatter % ( err ? "true" : "false") % err.get_message();
1360 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 79, formatter.str(), __FILE__, __LINE__ );
1365 * main loop of virtualservice(TCP)
1370 void l7vs::virtualservice_tcp::run(){
1371 Logger funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function : void virtualservice_tcp::run()", __FILE__, __LINE__ );
1373 if( pool_sessions.size() == 0 ){
1374 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.", __FILE__, __LINE__ );
1377 boost::asio::socket_base::receive_buffer_size option(8192 * 192);
1378 acceptor_.set_option(option);
1379 //set socket option TCP_DEFER_ACCEPT
1380 if(defer_accept_opt){
1381 boost::system::error_code ec;
1382 size_t len = sizeof(defer_accept_val);
1383 boost::asio::detail::socket_ops::setsockopt(acceptor_.native(),IPPROTO_TCP,TCP_DEFER_ACCEPT,&defer_accept_val,len,ec);
1386 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 17, "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__ );
1392 //switch active a session
1393 session_thread_control* stc_ptr;
1395 stc_ptr = pool_sessions.pop();
1399 //regist accept event handler
1400 waiting_sessions.insert( stc_ptr->get_session().get(), stc_ptr );
1402 if (!ssl_virtualservice_mode_flag) {
1403 acceptor_.async_accept( stc_ptr->get_session()->get_client_socket(),
1404 boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr, boost::asio::placeholders::error ) );
1406 acceptor_.async_accept( stc_ptr->get_session()->get_client_ssl_socket().lowest_layer(),
1407 boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr, boost::asio::placeholders::error ) );
1409 //regist timer event handler
1410 calc_bps_timer->expires_from_now( boost::posix_time::milliseconds( param_data.bps_interval ) );
1411 calc_bps_timer->async_wait( boost::bind( &virtualservice_tcp::handle_throughput_update,
1412 this, boost::asio::placeholders::error ) );
1414 //register handle_replication_interrupt
1415 replication_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1416 replication_timer->async_wait( boost::bind( &virtualservice_tcp::handle_replication_interrupt,
1417 this, boost::asio::placeholders::error ) );
1418 //register handle_protomod_replication
1419 protomod_rep_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1420 protomod_rep_timer->async_wait( boost::bind( &virtualservice_tcp::handle_protomod_replication,
1421 this, boost::asio::placeholders::error ) );
1422 //register handle_schedmod_replication
1423 schedmod_rep_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1424 schedmod_rep_timer->async_wait( boost::bind( &virtualservice_tcp::handle_schedmod_replication,
1425 this, boost::asio::placeholders::error ) );
1427 //run dispatcher(start io_service loop)
1430 //stop all active sessions
1432 active_sessions.do_all( boost::bind( &session_thread_control::session_stop, _1 ) );
1442 void l7vs::virtualservice_tcp::stop(){
1443 Logger funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function : void virtualservice_tcp::stop()", __FILE__, __LINE__ );
1445 boost::system::error_code err;
1447 acceptor_.close( err );
1449 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__ );
1457 * increment active-connection count
1462 void l7vs::virtualservice_tcp::connection_active( const boost::asio::ip::tcp::endpoint& in ){
1463 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1464 boost::format formatter("in_function : void virtualservice_tcp::connection_active( "
1465 "const boost::asio::ip::tcp::endpoint& in ) : in = %s");
1467 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__ );
1470 for( std::list<realserver>::iterator itr = rs_list.begin();
1471 itr != rs_list.end();
1473 if( itr->tcp_endpoint == in ){
1474 itr->increment_active();
1481 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1482 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 83, "out_function : void virtualservice_tcp::connection_active()", __FILE__, __LINE__ );
1487 * increment in-active-connection (and decrement active-connection count)
1492 void l7vs::virtualservice_tcp::connection_inactive( const boost::asio::ip::tcp::endpoint& in ){
1493 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1494 boost::format formatter("in_function : void virtualservice_tcp::connection_inactive( "
1495 "const boost::asio::ip::tcp::endpoint& in ) : in = %s");
1497 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__ );
1500 for( std::list<realserver>::iterator itr = rs_list.begin();
1501 itr != rs_list.end();
1503 if( itr->tcp_endpoint == in ){
1504 itr->decrement_active();
1505 itr->increment_inact();
1512 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1513 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 85, "out_function : void virtualservice_tcp::connection_inactive()", __FILE__, __LINE__ );
1523 void l7vs::virtualservice_tcp::release_session( const tcp_session* session_ptr ){
1524 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1525 boost::format funclog_fmt("in_function : void virtualservice_tcp::release_session( "
1526 "const tcp_session* session_ptr ) : session_ptr = %d");
1527 funclog_fmt % session_ptr;
1528 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 86, funclog_fmt.str(), __FILE__, __LINE__ );
1531 session_thread_control* stc_ptr = active_sessions.find( session_ptr );
1532 if( unlikely( NULL == stc_ptr ) ){
1533 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1534 boost::format fmt( "session release fail : active_sessions.find( const tcp_session* session_ptr = %d )");
1536 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 87, fmt.str(), __FILE__, __LINE__ );
1537 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 88, "out_function : void virtualservice_tcp::release_session( const boost::thread::id thread_id )", __FILE__, __LINE__ );
1542 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1543 boost::format fmt1( "pool_session.size = %d" );
1544 fmt1 % pool_sessions.size();
1545 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 89, fmt1.str(), __FILE__, __LINE__ );
1546 boost::format fmt2( "active_session.size = %d" );
1547 fmt2 % active_sessions.size();
1548 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 90, fmt2.str(), __FILE__, __LINE__ );
1549 boost::format fmt3( "active_count = %d" );
1550 fmt3 % active_count.get();
1551 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 91, fmt3.str(), __FILE__, __LINE__ );
1553 active_sessions.erase( session_ptr );
1554 stc_ptr->get_session()->initialize();
1556 if( likely( pool_sessions.push( stc_ptr ) ) ){
1561 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1562 boost::format fmt1( "pool_session.size = %d" );
1563 fmt1 % pool_sessions.size();
1564 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 92, fmt1.str(), __FILE__, __LINE__ );
1565 boost::format fmt2( "active_session.size = %d" );
1566 fmt2 % active_sessions.size();
1567 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 93, fmt2.str(), __FILE__, __LINE__ );
1568 boost::format fmt3( "active_count = %d" );
1569 fmt3 % active_count.get();
1570 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 94, fmt3.str(), __FILE__, __LINE__ );
1572 boost::format funclog_fmt("out_function : void virtualservice_tcp::release_session( "
1573 "const tcp_session* session_ptr ) : session_ptr = %d");
1574 funclog_fmt % session_ptr;
1575 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 95, funclog_fmt.str(), __FILE__, __LINE__ );
1580 // set_socket_option
1582 void l7vs::virtualservice_tcp::set_socket_option(){
1584 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1585 boost::format funclog_fmt("in_function : void virtualservice_tcp::et_socket_option");
1586 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 96, funclog_fmt.str(), __FILE__, __LINE__ );
1589 // socket option check & set
1590 //! is set option TCP_DEFER_ACCEPT
1591 defer_accept_opt = false;
1592 //! TCP_DEFER_ACCEPT option value
1593 defer_accept_val = 0;
1595 //! TCP_NODELAY (false:not set,true:set option)
1596 set_sock_opt.nodelay_opt = false;
1597 //! TCP_NODELAY option value (false:off,true:on)
1598 set_sock_opt.nodelay_val = false;
1599 //! TCP_CORK (false:not set,true:set option)
1600 set_sock_opt.cork_opt = false;
1601 //! TCP_CORK option value (false:off,true:on)
1602 set_sock_opt.cork_val = false;
1603 //! TCP_QUICKACK (false:not set,true:set option)
1604 set_sock_opt.quickack_opt = false;
1605 //! TCP_QUICKACK option value (false:off,true:on)
1606 set_sock_opt.quickack_val = false;
1608 // set socket option
1609 if ( element.socket_option_tcp_defer_accept != 0 ) {
1610 defer_accept_opt = true;
1611 if ( element.socket_option_tcp_defer_accept == 1 ) {
1612 defer_accept_val = 1;
1616 if ( element.socket_option_tcp_nodelay != 0 ) {
1617 set_sock_opt.nodelay_opt = true;
1618 if ( element.socket_option_tcp_nodelay == 1 ) {
1619 set_sock_opt.nodelay_val = true;
1623 if ( element.socket_option_tcp_cork != 0 ) {
1624 set_sock_opt.cork_opt = true;
1625 if ( element.socket_option_tcp_cork == 1 ) {
1626 set_sock_opt.cork_val = true;
1630 if ( element.socket_option_tcp_quickack != 0 ) {
1632 set_sock_opt.quickack_opt = true;
1633 if ( element.socket_option_tcp_quickack == 1 ) {
1634 set_sock_opt.quickack_val = true;
1638 //----Debug log----------------------------------------------------------------------
1639 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1640 boost::format formatter("set_socket_option"
1641 " defer_accept_opt[%s] defer_accept_val[%d]"
1642 " nodelay_opt[%s] nodelay_val[%s]"
1643 " cork_opt[%s] cork_val[%s]"
1644 " quickack_opt[%s]" "quickack_val[%s]");
1645 formatter %(defer_accept_opt ? "true" : "false") %defer_accept_val
1646 %(set_sock_opt.nodelay_opt ? "true" : "false") %(set_sock_opt.nodelay_val ? "true" : "false")
1647 %(set_sock_opt.cork_opt ? "true" : "false") %(set_sock_opt.cork_val ? "true" : "false")
1648 %(set_sock_opt.quickack_opt ? "true" : "false") %(set_sock_opt.quickack_val ? "true" : "false");
1649 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 97, formatter.str(), __FILE__, __LINE__ );
1651 //----Debug log----------------------------------------------------------------------
1656 //! get private key file password (for callback function)
1657 //! @return password string
1658 std::string l7vs::virtualservice_tcp::get_ssl_password()
1660 //*-------- DEBUG LOG --------*/
1661 if (unlikely(LOG_LV_DEBUG ==
1662 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1663 std::stringstream buf;
1664 buf << "in_function : ";
1665 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password()";
1666 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 98, buf.str(),
1667 __FILE__, __LINE__ );
1669 //*------ DEBUG LOG END ------*/
1671 // Get password from file.
1672 std::string retstr = "";
1674 char buf[MAX_SSL_PASSWD_SIZE + 3];
1675 if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1677 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1678 "Password file cannot open.", __FILE__, __LINE__ );
1680 if (fgets(buf, MAX_SSL_PASSWD_SIZE + 3, fp) == NULL) {
1681 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
1682 "Password not found in file.",
1683 __FILE__, __LINE__ );
1685 if ( strlen(buf) > MAX_SSL_PASSWD_SIZE ) {
1686 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1687 "Password is too long.",
1688 __FILE__, __LINE__ );
1690 buf[strlen(buf) - 1] = '\0';
1697 //*-------- DEBUG LOG --------*/
1698 if (unlikely(LOG_LV_DEBUG ==
1699 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1700 std::stringstream buf;
1701 buf << "out_function : ";
1702 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password() : ";
1703 buf << "retstr = " << retstr;
1704 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 99, buf.str(),
1705 __FILE__, __LINE__ );
1707 //*------ DEBUG LOG END ------*/
1713 //! Convert verify option string to intger(#define).
1715 //! @param[in] opt_string option string
1716 //! @retval ret option value
1717 //! @retval -1 no match
1718 int l7vs::virtualservice_tcp::conv_verify_option(std::string opt_string)
1720 //*-------- DEBUG LOG --------*/
1721 if (unlikely(LOG_LV_DEBUG ==
1722 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1723 std::stringstream buf;
1724 buf << "in_function : ";
1725 buf << "int virtualservice_tcp::conv_verify_option";
1726 buf << "(std::string opt_string) : ";
1727 buf << "opt_string = " << opt_string;
1728 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 100, buf.str(),
1729 __FILE__, __LINE__ );
1731 //*------ DEBUG LOG END ------*/
1735 // /usr/include/openssl/ssl.h
1736 // #define SSL_VERIFY_NONE 0x00
1737 // #define SSL_VERIFY_PEER 0x01
1738 // #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
1739 // #define SSL_VERIFY_CLIENT_ONCE 0x04
1741 if (opt_string == "SSL_VERIFY_NONE") {
1742 ret = SSL_VERIFY_NONE;
1743 } else if (opt_string == "SSL_VERIFY_PEER") {
1744 ret = SSL_VERIFY_PEER;
1745 } else if (opt_string == "SSL_VERIFY_FAIL_IF_NO_PEER_CERT") {
1746 ret = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1747 } else if (opt_string == "SSL_VERIFY_CLIENT_ONCE") {
1748 ret = SSL_VERIFY_CLIENT_ONCE;
1750 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
1751 "verify option string no match.",
1752 __FILE__, __LINE__ );
1755 //*-------- DEBUG LOG --------*/
1756 if (unlikely(LOG_LV_DEBUG ==
1757 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1758 std::stringstream buf;
1759 buf << "out_function : ";
1760 buf << "int virtualservice_tcp::conv_verify_option";
1761 buf << "(std::string opt_string) : ";
1762 buf << "return_value = " << ret;
1763 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 101, buf.str(),
1764 __FILE__, __LINE__ );
1766 //*------ DEBUG LOG END ------*/
1767 // if ret == -1 then No match.
1772 // Convert SSL option string to intger(#define).
1774 // @param[in] opt_string option string
1775 // @retval ret option value
1776 // @retval -1 no match
1777 long int l7vs::virtualservice_tcp::conv_ssl_option(std::string opt_string)
1779 //*-------- DEBUG LOG --------*/
1780 if (unlikely(LOG_LV_DEBUG ==
1781 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1782 std::stringstream buf;
1783 buf << "in_function : ";
1784 buf << "long int virtualservice_tcp::conv_ssl_option";
1785 buf << "(std::string opt_string) : ";
1786 buf << "opt_string = " << opt_string;
1787 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 102, buf.str(),
1788 __FILE__, __LINE__ );
1790 //*------ DEBUG LOG END ------*/
1794 // /usr/include/openssl/ssl.h
1795 // #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
1796 // #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
1797 // #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
1798 // #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
1799 // #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
1800 // #define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L
1801 // #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
1802 // #define SSL_OP_TLS_D5_BUG 0x00000100L
1803 // #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
1804 // #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L
1805 // #define SSL_OP_ALL 0x00000FF7L
1806 // #define SSL_OP_NO_QUERY_MTU 0x00001000L
1807 // #define SSL_OP_COOKIE_EXCHANGE 0x00002000L
1808 // #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
1809 // #define SSL_OP_SINGLE_ECDH_USE 0x00080000L
1810 // #define SSL_OP_SINGLE_DH_USE 0x00100000L
1811 // #define SSL_OP_EPHEMERAL_RSA 0x00200000L
1812 // #define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
1813 // #define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
1814 // #define SSL_OP_NO_SSLv2 0x01000000L
1815 // #define SSL_OP_NO_SSLv3 0x02000000L
1816 // #define SSL_OP_NO_TLSv1 0x04000000L
1817 // #define SSL_OP_PKCS1_CHECK_1 0x08000000L
1818 // #define SSL_OP_PKCS1_CHECK_2 0x10000000L
1819 // #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
1820 // #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
1821 if (opt_string == "SSL_OP_MICROSOFT_SESS_ID_BUG") {
1822 ret = SSL_OP_MICROSOFT_SESS_ID_BUG;
1823 } else if (opt_string == "SSL_OP_NETSCAPE_CHALLENGE_BUG") {
1824 ret = SSL_OP_NETSCAPE_CHALLENGE_BUG;
1825 } else if (opt_string == "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG") {
1826 ret = SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
1827 } else if (opt_string == "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG") {
1828 ret = SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
1829 } else if (opt_string == "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER") {
1830 ret = SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
1831 } else if (opt_string == "SSL_OP_MSIE_SSLV2_RSA_PADDING") {
1832 ret = SSL_OP_MSIE_SSLV2_RSA_PADDING;
1833 } else if (opt_string == "SSL_OP_SSLEAY_080_CLIENT_DH_BUG") {
1834 ret = SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
1835 } else if (opt_string == "SSL_OP_TLS_D5_BUG") {
1836 ret = SSL_OP_TLS_D5_BUG;
1837 } else if (opt_string == "SSL_OP_TLS_BLOCK_PADDING_BUG") {
1838 ret = SSL_OP_TLS_BLOCK_PADDING_BUG;
1839 } else if (opt_string == "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS") {
1840 ret = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
1841 } else if (opt_string == "SSL_OP_ALL") {
1842 // boost::asio::ssl::context::default_workarounds
1844 } else if (opt_string == "SSL_OP_NO_QUERY_MTU") {
1845 ret = SSL_OP_NO_QUERY_MTU;
1846 } else if (opt_string == "SSL_OP_COOKIE_EXCHANGE") {
1847 ret = SSL_OP_COOKIE_EXCHANGE;
1848 } else if (opt_string == "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION") {
1849 ret = SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
1850 } else if (opt_string == "SSL_OP_SINGLE_ECDH_USE") {
1851 ret = SSL_OP_SINGLE_ECDH_USE;
1852 } else if (opt_string == "SSL_OP_SINGLE_DH_USE") {
1853 // boost::asio::ssl::context::single_dh_use
1854 ret = SSL_OP_SINGLE_DH_USE;
1855 } else if (opt_string == "SSL_OP_EPHEMERAL_RSA") {
1856 ret = SSL_OP_EPHEMERAL_RSA;
1857 } else if (opt_string == "SSL_OP_CIPHER_SERVER_PREFERENCE") {
1858 ret = SSL_OP_CIPHER_SERVER_PREFERENCE;
1859 } else if (opt_string == "SSL_OP_TLS_ROLLBACK_BUG") {
1860 ret = SSL_OP_TLS_ROLLBACK_BUG;
1861 } else if (opt_string == "SSL_OP_NO_SSLv2") {
1862 // boost::asio::ssl::context::no_sslv2
1863 ret = SSL_OP_NO_SSLv2;
1864 } else if (opt_string == "SSL_OP_NO_SSLv3") {
1865 // boost::asio::ssl::context::no_sslv3
1866 ret = SSL_OP_NO_SSLv3;
1867 } else if (opt_string == "SSL_OP_NO_TLSv1") {
1868 // boost::asio::ssl::context::no_tlsv1
1869 ret = SSL_OP_NO_TLSv1;
1870 } else if (opt_string == "SSL_OP_PKCS1_CHECK_1") {
1871 ret = SSL_OP_PKCS1_CHECK_1;
1872 } else if (opt_string == "SSL_OP_PKCS1_CHECK_2") {
1873 ret = SSL_OP_PKCS1_CHECK_2;
1874 } else if (opt_string == "SSL_OP_NETSCAPE_CA_DN_BUG") {
1875 ret = SSL_OP_NETSCAPE_CA_DN_BUG;
1876 } else if (opt_string == "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG") {
1877 ret = SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
1879 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
1880 "ssl option string no match.",
1881 __FILE__, __LINE__ );
1884 //*-------- DEBUG LOG --------*/
1885 if (unlikely(LOG_LV_DEBUG ==
1886 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1887 std::stringstream buf;
1888 buf << "out_function : ";
1889 buf << "long int virtualservice_tcp::conv_ssl_option";
1890 buf << "(std::string opt_string) : ";
1891 buf << "return_value = " << ret;
1892 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 103, buf.str(),
1893 __FILE__, __LINE__ );
1895 //------ DEBUG LOG END ------*/
1896 // if ret == -1 then No match.
1901 //! get ssl parameter
1902 //! @return get ssl parameter result
1903 bool l7vs::virtualservice_tcp::get_ssl_parameter()
1905 //*-------- DEBUG LOG --------*/
1906 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1907 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 104,
1908 "in_function : bool virtualservice_tcp::get_ssl_parameter()",
1909 __FILE__, __LINE__ );
1911 //*------ DEBUG LOG END ------*/
1912 typedef std::vector< std::string > string_vector_type;
1915 string_vector_type string_vector;
1916 l7vs::error_code err;
1917 bool retbool = false;
1920 // param init ( ssl configuration file )
1921 if (unlikely(!param.init(l7vs::PARAM_COMP_SSL, ssl_file_name))) {
1922 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 24,
1923 "SSL config file read error.",
1924 __FILE__, __LINE__ );
1928 //// SSL context parameter
1929 // Get parameter "ca_dir".
1930 ca_dir = param.get_string(l7vs::PARAM_COMP_SSL, "ca_dir",
1931 err, ssl_file_name);
1932 if (unlikely(err) || ca_dir == "") {
1933 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 9,
1934 "ca_dir parameter not found. Use default value.",
1935 __FILE__, __LINE__ );
1936 ca_dir = DEFAULT_SSL_CA_DIR;
1939 // Get parameter "ca_file".
1940 ca_file = param.get_string(l7vs::PARAM_COMP_SSL, "ca_file",
1941 err, ssl_file_name);
1942 if (unlikely(err)) {
1943 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 25,
1944 "Cannot get ca_file parameter.",
1945 __FILE__, __LINE__ );
1949 // Get parameter "cert_chain_dir".
1950 cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
1954 if (unlikely(err) || cert_chain_dir == "") {
1955 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 10,
1956 "cert_chain_dir parameter not found. Use default value.",
1957 __FILE__, __LINE__ );
1958 cert_chain_dir = DEFAULT_SSL_CERT_CHAIN_DIR;
1961 // Get parameter "cert_chain_file".
1962 cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
1966 if (unlikely(err) || cert_chain_file == "") {
1967 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 26,
1968 "Cannot get cert_chain_file parameter.",
1969 __FILE__, __LINE__ );
1973 // Get parameter "private_key_dir".
1974 private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
1978 if (unlikely(err) || private_key_dir == "") {
1979 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 11,
1980 "private_key_dir parameter not found. Use default value.",
1981 __FILE__, __LINE__ );
1982 private_key_dir = DEFAULT_SSL_PRIVATE_KEY_DIR;
1985 // Get parameter "private_key_file".
1986 private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
1990 if (unlikely(err) || private_key_file == "") {
1991 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 27,
1992 "Cannot get private_key_file parameter.",
1993 __FILE__, __LINE__ );
1997 // Get parameter "private_key_filetype".
1998 // and convert string to filetype define value.
2000 // /usr/include/openssl/ssl.h
2001 // #define SSL_FILETYPE_PEM X509_FILETYPE_PEM ->1
2002 // #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 ->2
2005 std::string filetype_str = param.get_string(
2006 l7vs::PARAM_COMP_SSL,
2007 "private_key_filetype",
2010 if (unlikely(err) || filetype_str == "") {
2011 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 12,
2012 "private_key_filetype parameter not found. Use default value.",
2013 __FILE__, __LINE__ );
2014 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
2015 } else if (filetype_str == "SSL_FILETYPE_PEM") {
2016 private_key_filetype = boost::asio::ssl::context::pem;
2017 } else if (filetype_str == "SSL_FILETYPE_ASN1") {
2018 private_key_filetype = boost::asio::ssl::context::asn1;
2020 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
2021 "private_key_filetype convert error.",
2022 __FILE__, __LINE__ );
2026 // Get parameter "private_key_passwd_dir".
2027 private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2028 "private_key_passwd_dir",
2031 if (unlikely(err) || private_key_passwd_dir == "") {
2032 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 13,
2033 "private_key_passwd_dir parameter not found. Use default value.",
2034 __FILE__, __LINE__ );
2035 private_key_passwd_dir = DEFAULT_SSL_PRIVATE_KEY_PASSWD_DIR;
2038 // Get parameter "private_key_passwd_file".
2039 private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2040 "private_key_passwd_file",
2043 if (unlikely(err) || private_key_passwd_file == "") {
2044 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
2045 "Cannot get private_key_passwd_file parameter.",
2046 __FILE__, __LINE__ );
2050 // Get parameter "verify_options".
2051 param.get_multistring(l7vs::PARAM_COMP_SSL,
2056 if (unlikely(err)) {
2057 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 14,
2058 "verify_options parameter not found. Use default value.",
2059 __FILE__, __LINE__ );
2060 verify_options = DEFAULT_SSL_VERIFY_OPTIONS;
2062 // Make verify option bit data.
2063 for (string_vector_type::iterator itr = string_vector.begin();
2064 itr != string_vector.end(); ++itr) {
2065 // Convert string to define value.
2066 int int_val = conv_verify_option(*itr);
2067 if (unlikely(int_val == -1)) {
2068 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 30,
2069 "verify_options convert error.",
2070 __FILE__, __LINE__ );
2073 verify_options = (verify_options | int_val);
2077 // Get parameter "verify_cert_depth".
2078 verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2079 "verify_cert_depth",
2082 if (unlikely(err)) {
2083 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 15,
2084 "verify_cert_depth parameter not found. Use default value.",
2085 __FILE__, __LINE__ );
2086 verify_cert_depth = DEFAULT_SSL_VERIFY_CERT_DEPTH;
2087 } else if (unlikely(verify_cert_depth < 0 ||
2088 verify_cert_depth > INT_MAX)) {
2089 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 31,
2090 "Invalid verify_cert_depth parameter value.",
2091 __FILE__, __LINE__ );
2095 // Get parameter "ssl_options".
2096 // and Check dh parameter file use or not.
2097 is_tmp_dh_use = false;
2098 param.get_multistring(l7vs::PARAM_COMP_SSL,
2103 if (unlikely(err)) {
2104 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 16,
2105 "ssl_options parameter not found. Use default value.",
2106 __FILE__, __LINE__ );
2107 ssl_options = DEFAULT_SSL_OPTIONS;
2108 is_tmp_dh_use = true;
2110 // Make ssl option bit data.
2111 for (string_vector_type::iterator itr = string_vector.begin();
2112 itr != string_vector.end(); ++itr) {
2113 // Convert string to define value.
2114 long int longint_val = conv_ssl_option(*itr);
2115 if (unlikely(longint_val == -1)) {
2116 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 32,
2117 "ssl_options convert error.",
2118 __FILE__, __LINE__ );
2120 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2121 is_tmp_dh_use = true;
2123 ssl_options = (ssl_options | longint_val);
2127 if (is_tmp_dh_use) {
2128 // Get parameter "tmp_dh_dir".
2129 tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2133 if (unlikely(err) || tmp_dh_dir == "") {
2134 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
2135 "tmp_dh_dir parameter not found. Use default value.",
2136 __FILE__, __LINE__ );
2137 tmp_dh_dir = DEFAULT_SSL_TMP_DH_DIR;
2139 // Get parameter "tmp_dh_file".
2140 tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2144 if (unlikely(err) || tmp_dh_file == "") {
2145 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 33,
2146 "Cannot get tmp_dh_file parameter.",
2147 __FILE__, __LINE__ );
2152 // Get parameter "cipher_list".
2153 cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2157 if (unlikely(err) || cipher_list == "") {
2158 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 18,
2159 "cipher_list parameter not found. Use default value.",
2160 __FILE__, __LINE__ );
2161 cipher_list = DEFAULT_SSL_CIPHER_LIST;
2164 //// SSL session cache parameter
2165 // Get parameter "session_cache".
2166 is_session_cache_use = false;
2167 std::string cache_str = param.get_string(l7vs::PARAM_COMP_SSL,
2171 if (unlikely(err) || cache_str == "") {
2172 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
2173 "session_cache parameter not found. Use default value.",
2174 __FILE__, __LINE__ );
2175 is_session_cache_use = true;
2176 } else if (cache_str == "on") {
2177 is_session_cache_use = true;
2178 } else if (cache_str == "off") {
2179 is_session_cache_use = false;
2181 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2182 "Invalid session_cache parameter value.",
2183 __FILE__, __LINE__ );
2187 if (is_session_cache_use) {
2188 session_cache_mode = DEFAULT_SSL_SESSION_CACHE_MODE;
2189 // Get parameter "session_cache_size".
2190 session_cache_size = param.get_int(l7vs::PARAM_COMP_SSL,
2191 "session_cache_size",
2194 if (unlikely(err)) {
2195 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
2196 "session_cache_size parameter not found. Use default value.",
2197 __FILE__, __LINE__ );
2198 session_cache_size = DEFAULT_SSL_SESSION_CACHE_SIZE;
2199 } else if (session_cache_size < 0 ||
2200 session_cache_size > INT_MAX) {
2201 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 35,
2202 "Invalid session_cache_size parameter value.",
2203 __FILE__, __LINE__ );
2206 // Get parameter "session_cache_timeout".
2207 session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2208 "session_cache_timeout",
2211 if (unlikely(err)) {
2212 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
2213 "session_cache_timeout parameter not found. Use default value.",
2214 __FILE__, __LINE__ );
2215 session_cache_timeout = DEFAULT_SSL_SESSION_CACHE_TIMEOUT;
2216 } else if (session_cache_timeout < 0 ||
2217 session_cache_timeout > INT_MAX) {
2218 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 36,
2219 "Invalid session_cache_timeout parameter value.",
2220 __FILE__, __LINE__ );
2224 session_cache_mode = SSL_SESS_CACHE_OFF;
2227 //// SSL handshake timer parameter
2228 // Get parameter "timeout_sec".
2229 handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2233 if (unlikely(err)) {
2234 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2235 "timeout_sec parameter not found. Use default value.",
2236 __FILE__, __LINE__ );
2237 handshake_timeout = DEFAULT_SSL_HANDSHAKE_TIMEOUT;
2238 } else if (handshake_timeout <= 0 || handshake_timeout > INT_MAX) {
2239 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 37,
2240 "Invalid timeout_sec parameter value.",
2241 __FILE__, __LINE__ );
2251 //*-------- DEBUG LOG --------*/
2252 if (unlikely(LOG_LV_DEBUG ==
2253 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2254 std::stringstream buf;
2255 buf<<"out_function : bool virtualservice_tcp::get_ssl_parameter() : ";
2256 buf<<"ca_dir = " << ca_dir << ", ";
2257 buf<<"ca_file = " << ca_file << ", ";
2258 buf<<"cert_chain_dir = " << cert_chain_dir << ", ";
2259 buf<<"cert_chain_file = " << cert_chain_file << ", ";
2260 buf<<"private_key_dir = " << private_key_dir << ", ";
2261 buf<<"private_key_file = " << private_key_file << ", ";
2262 buf<<"private_key_filetype = " << private_key_filetype << ", ";
2263 buf<<"private_key_passwd_dir = " << private_key_passwd_dir << ", ";
2264 buf<<"private_key_passwd_file = "<< private_key_passwd_file << ", ";
2265 buf<<"verify_options = " << verify_options << ", ";
2266 buf<<"verify_cert_depth = " << verify_cert_depth << ", ";
2267 buf<<"ssl_options = " << ssl_options << ", ";
2268 if (is_tmp_dh_use) {
2269 buf<< "tmp_dh_dir = " << tmp_dh_dir << ", ";
2270 buf<< "tmp_dh_file = " << tmp_dh_file << ", ";
2272 buf<<"cipher_list = " << cipher_list << ", ";
2273 buf<<"session_cache_mode = " << session_cache_mode << ", ";
2274 if (is_session_cache_use) {
2275 buf<<"session_cache_size = " << session_cache_size << ", ";
2276 buf<<"session_cache_timeout = "<< session_cache_timeout << ", ";
2278 buf<<"handshake_timeout = " << handshake_timeout;
2279 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2281 __FILE__, __LINE__ );
2283 //*------ DEBUG LOG END ------*/
2288 // set ssl context and ssl session cache configuration
2289 // @return set ssl config result
2290 bool l7vs::virtualservice_tcp::set_ssl_config()
2292 //*-------- DEBUG LOG --------*/
2293 if (unlikely(LOG_LV_DEBUG ==
2294 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2295 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 106,
2296 "in_function : bool virtualservice_tcp::set_ssl_config()",
2297 __FILE__, __LINE__ );
2299 //*------ DEBUG LOG END ------*/
2301 bool retbool = false;
2304 //// SSL context setting.
2306 if (ca_file.size() == 0) {
2307 // specified CA path.
2309 sslcontext.add_verify_path(ca_dir);
2310 } catch (std::exception& e) {
2311 std::stringstream buf;
2312 buf << "Set root CA path error : " << e.what() << ".";
2313 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 107,
2315 __FILE__, __LINE__ );
2319 // specified CA file.
2321 sslcontext.load_verify_file(ca_dir + ca_file);
2322 } catch (std::exception& e) {
2323 std::stringstream buf;
2324 buf << "Set root CA file error : " << e.what() << ".";
2325 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 108,
2327 __FILE__, __LINE__ );
2332 // Set certificate chain file.
2334 sslcontext.use_certificate_chain_file(
2335 cert_chain_dir + cert_chain_file);
2336 } catch (std::exception& e) {
2337 std::stringstream buf;
2338 buf << "Set certificate chain file error : " << e.what() << ".";
2339 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 109, buf.str(),
2340 __FILE__, __LINE__ );
2344 // Set password callback function.
2346 sslcontext.set_password_callback(
2347 boost::bind(&virtualservice_tcp::get_ssl_password, this));
2348 } catch (std::exception& e) {
2349 std::stringstream buf;
2350 buf << "Set password callback error : " << e.what() << ".";
2351 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 110, buf.str(),
2352 __FILE__, __LINE__ );
2356 // Set private key file and filetype.
2358 sslcontext.use_private_key_file(
2359 private_key_dir + private_key_file, private_key_filetype);
2360 } catch (std::exception& e) {
2361 std::stringstream buf;
2362 buf <<"Set private key file and filetype error : "<<e.what()<<".";
2363 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 111, buf.str(),
2364 __FILE__, __LINE__ );
2368 // Set verify options on the context.
2370 sslcontext.set_verify_mode(verify_options);
2371 } catch (std::exception& e) {
2372 std::stringstream buf;
2373 buf << "Set verify option error : " << e.what() << ".";
2374 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 112, buf.str(),
2375 __FILE__, __LINE__ );
2379 // Set verify depth on the context.
2380 SSL_CTX_set_verify_depth(sslcontext.impl(), verify_cert_depth);
2382 // Set SSL options on the context.
2384 sslcontext.set_options(ssl_options);
2385 } catch (std::exception& e) {
2386 std::stringstream buf;
2387 buf << "Set SSL option error : " << e.what() << ".";
2388 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 113, buf.str(),
2389 __FILE__, __LINE__ );
2393 // Set temporary Diffie-Hellman parameters file.
2394 if (is_tmp_dh_use) {
2396 sslcontext.use_tmp_dh_file(tmp_dh_dir + tmp_dh_file);
2397 } catch (std::exception& e) {
2398 std::stringstream buf;
2399 buf << "Set tmp DH file error : " << e.what() << ".";
2400 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 114,
2402 __FILE__, __LINE__ );
2408 // Set cipher list on the context.
2409 if (unlikely(SSL_CTX_set_cipher_list(sslcontext.impl(),
2410 cipher_list.c_str()) != 1)) {
2411 std::stringstream buf;
2412 buf << "Set cipher list error.";
2413 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 115,
2415 __FILE__, __LINE__ );
2419 //// SSL session cache setting.
2420 if (is_session_cache_use) {
2421 // Set session id context on the context.
2422 if (unlikely( SSL_CTX_set_session_id_context(
2424 (const unsigned char *)"ultramonkey", 11) != 1)) {
2425 std::stringstream buf;
2426 buf << "Set session id context error.";
2427 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 116,
2429 __FILE__, __LINE__ );
2433 // Set session cache mode on the context.
2434 SSL_CTX_set_session_cache_mode(
2435 sslcontext.impl(),session_cache_mode);
2437 // Set session cache size on the context.
2438 SSL_CTX_sess_set_cache_size(sslcontext.impl(), session_cache_size);
2440 // Set session cache timeout on the context.
2441 SSL_CTX_set_timeout(sslcontext.impl(), session_cache_timeout);
2444 // session cache OFF.
2445 SSL_CTX_set_session_cache_mode(sslcontext.impl(),
2446 SSL_SESS_CACHE_OFF);
2454 //*-------- DEBUG LOG --------*/
2455 if (unlikely(LOG_LV_DEBUG ==
2456 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2457 std::stringstream buf;
2458 buf << "out_function : bool virtualservice_tcp::set_ssl_config() : ";
2459 get_ssl_config(buf);
2460 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 117, buf.str(),
2461 __FILE__, __LINE__ );
2463 //*------ DEBUG LOG END ------*/
2468 // flush ssl session
2469 void l7vs::virtualservice_tcp::flush_ssl_session()
2471 // check expired cached sessions and do flushing
2472 // Need ssl_context lock?
2473 SSL_CTX_flush_sessions(sslcontext.impl(), time(0));
2477 // get ssl configuration form ssl context. (for debug)
2478 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream& buf)
2480 buf<<"SSL configuration information : ";
2481 buf<<"Verify mode[" << SSL_CTX_get_verify_mode(sslcontext.impl()) << "] ";
2482 buf<<"Verify depth["<< SSL_CTX_get_verify_depth(sslcontext.impl())<< "] ";
2483 buf<<"SSL options[" << SSL_CTX_get_options(sslcontext.impl()) << "] ";
2484 buf<<"Cache mode[" << SSL_CTX_get_session_cache_mode(sslcontext.impl());
2486 buf<<"Cache size["<<SSL_CTX_sess_get_cache_size(sslcontext.impl())<< "] ";
2487 buf<<"Cache timeout[" << SSL_CTX_get_timeout(sslcontext.impl()) << "] ";
2491 // get ssl session cache information form ssl context. (for debug)
2492 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream& buf)
2494 buf << "SSL session cache information : ";
2495 buf << "Session number[" << SSL_CTX_sess_number(sslcontext.impl()) << "] ";
2496 buf << "Accept[" << SSL_CTX_sess_accept(sslcontext.impl()) << "] ";
2497 buf << "Accept good[" << SSL_CTX_sess_accept_good(sslcontext.impl()) << "] ";
2498 buf << "Accept renegotiate[" << SSL_CTX_sess_accept_renegotiate(sslcontext.impl()) << "] ";
2499 buf << "Hits[" << SSL_CTX_sess_hits(sslcontext.impl()) << "] ";
2500 buf << "Misses[" << SSL_CTX_sess_misses(sslcontext.impl()) << "] ";
2501 buf << "Timeouts[" << SSL_CTX_sess_timeouts(sslcontext.impl()) << "] ";
2502 buf << "Cache full[" << SSL_CTX_sess_cache_full(sslcontext.impl()) << "] ";