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("")
57 * virtualservice_tcp class destructor.
59 l7vs::virtualservice_tcp::~virtualservice_tcp(){
63 * replication interrupt event
68 void l7vs::virtualservice_tcp::handle_replication_interrupt( const boost::system::error_code& err ){
69 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
70 boost::format fmt("in_function : void virtualservice_tcp::handle_replication_interrupt( "
71 "const boost::system::error_code& err ) : err = %s, err.message = %s");
72 fmt % ( err ? "true" : "false") % err.message();
73 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 20, fmt.str(), __FILE__, __LINE__ );
76 if( unlikely( err ) ){
78 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, err.message(), __FILE__, __LINE__ );
83 replication& rep_noconst = const_cast<replication&>( rep );
85 if( replication::REPLICATION_SINGLE == rep_noconst.get_status() ){
86 Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "replication mode is single.", __FILE__, __LINE__ );
90 std::stringstream tmp_tcp_ep;
91 tmp_tcp_ep << element.tcp_accept_endpoint;
92 std::stringstream tmp_udp_ep;
93 tmp_udp_ep << element.udp_recv_endpoint;
94 std::stringstream tmp_sorry_ep;
95 tmp_sorry_ep << element.sorry_endpoint;
97 //get replication area
98 unsigned int rep_size = 0;
99 replication_header* rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
100 if( (rep_header_ptr == NULL) || (0 == rep_size) ){
101 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
106 if( ( rep_size * DATA_SIZE ) <
107 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
108 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
112 //lock replication area
113 rep_noconst.lock( REP_AREA_NAME );
115 //read header value and set loop count
116 unsigned int loop_cnt = rep_header_ptr->data_num;
117 //if data_num over MAX_REPLICATION_DATA_NUM, data_num = 0
118 if( static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt )
121 //set start pointer(pointer of replication_data)
122 replication_data* rep_data_ptr = reinterpret_cast<replication_data*>( ++rep_header_ptr );
125 for( unsigned int i = 0; i < loop_cnt; ++i ){
126 //check equal udpmode and tcp_accept_endpoint
127 if( (rep_data_ptr->udpmode == element.udpmode )&&
128 ( 0 == strncmp( rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 47 ) ) ){
132 //increment data pointer
136 //if it is new data, increment data num.
138 rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
139 ++(rep_header_ptr->data_num);
141 //write replication data
142 rep_data_ptr->udpmode = element.udpmode;
143 strncpy( rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 48 );
144 strncpy( rep_data_ptr->udp_endpoint, tmp_udp_ep.str().c_str(), 48 );
145 rep_data_ptr->sorry_maxconnection = element.sorry_maxconnection;
146 strncpy( rep_data_ptr->sorry_endpoint, tmp_sorry_ep.str().c_str(), 48 );
147 rep_data_ptr->sorry_flag = element.sorry_flag;
148 rep_data_ptr->qos_up = element.qos_upstream;
149 rep_data_ptr->qos_down = element.qos_downstream;
151 //unlock replication area
152 rep_noconst.unlock( REP_AREA_NAME );
154 //register handle_replication_interrupt
155 replication_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
156 replication_timer->async_wait( boost::bind( &virtualservice_tcp::handle_replication_interrupt,
157 this, boost::asio::placeholders::error ) );
159 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
160 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 21, "out_function : void virtualservice_tcp::handle_replication_interrupt( const boost::system::error_code& err )", __FILE__, __LINE__ );
165 * read replication data
167 * @param read_replicationdata
171 void l7vs::virtualservice_tcp::read_replicationdata(){
172 Logger funclog( LOG_CAT_L7VSD_VIRTUALSERVICE, 22, "function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
174 replication& rep_noconst = const_cast<replication&>( rep );
176 if( replication::REPLICATION_SINGLE == rep_noconst.get_status() ){
177 Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, "replication mode is single.", __FILE__, __LINE__ );
181 unsigned int rep_size = 0;
182 replication_header* rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
183 if( (rep_header_ptr == NULL) || (0 == rep_size) ){
184 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 3, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
185 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
186 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 23, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
192 if( ( rep_size * DATA_SIZE ) <
193 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
194 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 4, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
195 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
196 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 24, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
200 //lock replication area
201 rep_noconst.lock( REP_AREA_NAME );
203 //read header value and set loop count
204 unsigned int loop_cnt = rep_header_ptr->data_num;
205 //if data_num over MAX_REPLICATION_DATA_NUM, set data_num = 0
206 if( static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt ){
207 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 5, 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, 25, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
211 rep_header_ptr->data_num = 0;
212 rep_noconst.unlock( REP_AREA_NAME );
216 //set start pointer(pointer of replication_data)
217 replication_data* rep_data_ptr = reinterpret_cast<replication_data*>( ++rep_header_ptr );
220 for( unsigned int i = 0; i < loop_cnt; ++i ){
221 //get tcp endpointdata
222 std::string tmpstr = rep_data_ptr->tcp_endpoint;
224 unsigned short portno;
226 portno = boost::lexical_cast<unsigned short>( tmpstr.substr( (tmpstr.rfind( ":" )+1) ) );
228 catch( const boost::bad_lexical_cast& err ){
231 if( tmpstr[0] == '[' ){
233 ipaddr = tmpstr.substr( 1, (tmpstr.rfind( "]" )-1) );
236 ipaddr = tmpstr.substr( 0, tmpstr.rfind( ":" ) );
238 //check equal udpmode and tcp_accept_endpoint
239 if( (rep_data_ptr->udpmode == element.udpmode )&&
240 ( tcp_endpoint_type( boost::asio::ip::address::from_string( ipaddr ), portno ) == element.tcp_accept_endpoint ) ){
241 element.sorry_maxconnection = rep_data_ptr->sorry_maxconnection;
242 tmpstr = rep_data_ptr->sorry_endpoint;
244 portno = boost::lexical_cast<unsigned short>( tmpstr.substr( (tmpstr.rfind( ":" )+1) ) );
246 catch( const boost::bad_lexical_cast& err ){
249 if( tmpstr[0] == '[' ){
251 ipaddr = tmpstr.substr( 1, (tmpstr.rfind( "]" )-1) );
254 ipaddr = tmpstr.substr( 0, tmpstr.rfind( ":" ) );
256 element.sorry_endpoint =
257 tcp_endpoint_type( boost::asio::ip::address::from_string( ipaddr ), portno );
258 element.sorry_flag = rep_data_ptr->sorry_flag;
259 element.qos_upstream = rep_data_ptr->qos_up;
260 element.qos_downstream = rep_data_ptr->qos_down;
263 //increment data pointer
267 //unlock replication area
268 rep_noconst.unlock( REP_AREA_NAME );
270 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
271 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 26, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
278 * @param handle_accept
282 void l7vs::virtualservice_tcp::handle_accept( const l7vs::session_thread_control* stc_ptr, const boost::system::error_code& err ){
283 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
284 boost::format funclog_fmt("in_function : void virtualservice_tcp::handle_accept( "
285 "const boost::shared_ptr<session_thread_control> , "
286 "const boost::system::error_code& err ) : err = %s, err.message = %s");
287 funclog_fmt % ( err ? "true" : "false") % err.message();
288 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 27, funclog_fmt.str(), __FILE__, __LINE__ );
291 session_thread_control* stc_ptr_noconst = const_cast<session_thread_control*>( stc_ptr );
293 if( unlikely( err ) ){
295 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, err.message(), __FILE__, __LINE__ );
299 tcp_session* tmp_session = stc_ptr_noconst->get_session().get();
301 // ssl session cache flush
302 if( ( ssl_file_name != "" ) && ( is_session_cache_use == true ) ) {
304 //*-------- DEBUG LOG --------*/
305 if (unlikely(LOG_LV_DEBUG ==
306 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
307 std::stringstream buf;
308 buf << "virtualservice_tcp::handle_accept() : ";
309 buf << "ssl session cache flush before : ";
310 get_ssl_session_cache_info(buf);
311 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
313 __FILE__, __LINE__ );
315 //*------ DEBUG LOG END ------*/
317 long ssl_cache_num = SSL_CTX_sess_number(sslcontext.impl());
318 if ( ssl_cache_num >= session_cache_size ) {
322 //*-------- DEBUG LOG --------*/
323 if (unlikely(LOG_LV_DEBUG ==
324 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
325 std::stringstream buf;
326 buf << "virtualservice_tcp::handle_accept() : ";
327 buf << "ssl session cache flush after : ";
328 get_ssl_session_cache_info(buf);
329 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
331 __FILE__, __LINE__ );
333 //*------ DEBUG LOG END ------*/
337 // send access log output ON or OFF message to tcp_session
338 stc_ptr_noconst->session_access_log_output_mode_change( access_log_flag );
340 active_sessions.insert( tmp_session, stc_ptr_noconst );
342 //check sorry flag and status
343 if ( unlikely( ( 0 != element.sorry_flag ) ||
344 ( ( 0 < element.sorry_maxconnection ) &&
345 ( ( active_count.get() >= static_cast<size_t>( element.sorry_maxconnection ) ) ) ) ) ){
346 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
347 boost::format fmt( "Connection switch Sorry mode. : active_session.size = %d / active_count.get = %d" );
348 fmt % active_sessions.size() % active_count.get();
349 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 30, fmt.str(), __FILE__, __LINE__ );
351 stc_ptr_noconst->get_session()->set_virtual_service_message( tcp_session::SORRY_STATE_ENABLE );
354 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
355 boost::format fmt1( "active session thread id = %d" );
356 fmt1 % stc_ptr_noconst->get_upthread_id();
357 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 31, fmt1.str(), __FILE__, __LINE__ );
358 boost::format fmt2( "pool_session.size = %d" );
359 fmt2 % pool_sessions.size();
360 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 32, fmt2.str(), __FILE__, __LINE__ );
361 boost::format fmt3( "active_session.size = %d" );
362 fmt3 % active_sessions.size();
363 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 33, fmt3.str(), __FILE__, __LINE__ );
364 boost::format fmt4( "active_count = %d" );
365 fmt4 % active_count.get();
366 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 34, fmt4.str(), __FILE__, __LINE__ );
369 session_thread_control* tmp_stc_ptr = waiting_sessions.find( stc_ptr_noconst->get_session().get() );
370 waiting_sessions.erase( tmp_stc_ptr->get_session().get() );
372 stc_ptr_noconst->startupstream();
373 stc_ptr_noconst->startdownstream();
375 //waiting, pool_sessions.size become over 1
376 //pick up session from pool
377 session_thread_control* stc_ptr_register_accept;
379 stc_ptr_register_accept = pool_sessions.pop();
381 while( unlikely( !stc_ptr_register_accept ) );
383 //session add wait_sessions
384 boost::mutex::scoped_lock up_wait_lk( stc_ptr_register_accept->get_upthread_mutex() );
385 boost::mutex::scoped_lock down_wait_lk( stc_ptr_register_accept->get_downthread_mutex() );
387 waiting_sessions.insert( stc_ptr_register_accept->get_session().get(), stc_ptr_register_accept );
389 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
390 boost::format fmt1( "active session thread id = %d" );
391 fmt1 % stc_ptr_register_accept->get_upthread_id();
392 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 35, fmt1.str(), __FILE__, __LINE__ );
393 boost::format fmt2( "pool_session.size = %d" );
394 fmt2 % pool_sessions.size();
395 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 36, fmt2.str(), __FILE__, __LINE__ );
396 boost::format fmt3( "active_session.size = %d" );
397 fmt3 % active_sessions.size();
398 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 37, fmt3.str(), __FILE__, __LINE__ );
399 boost::format fmt4( "active_count = %d" );
400 fmt4 % active_count.get();
401 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 38, fmt4.str(), __FILE__, __LINE__ );
404 //regist accept event handler
405 if (!ssl_virtualservice_mode_flag) {
406 acceptor_.async_accept( stc_ptr_register_accept->get_session()->get_client_socket(),
407 boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr_register_accept, boost::asio::placeholders::error ) );
409 acceptor_.async_accept( stc_ptr_register_accept->get_session()->get_client_ssl_socket().lowest_layer(),
410 boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr_register_accept, boost::asio::placeholders::error ) );
413 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
414 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__ );
419 * initialize virtualservice(TCP)
424 void l7vs::virtualservice_tcp::initialize( l7vs::error_code& err ){
425 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
426 boost::format formatter("in_function : void virtualservice_tcp::initialize( "
427 "l7vs::error_code& err )");
428 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 40, formatter.str(), __FILE__, __LINE__ );
430 if( pool_sessions.size() != 0 ){
431 err.setter( true, "VirtualService already initialized." );
432 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
433 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
434 "l7vs::error_code& err ) : err = %s, err.message = %s");
435 formatter % ( err ? "true" : "false") % err.get_message();
436 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 41, formatter.str(), __FILE__, __LINE__ );
441 //load parameter value
442 load_parameter( err );
444 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
445 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
446 "l7vs::error_code& err ) : err = %s, err.message = %s");
447 formatter % ( err ? "true" : "false") % err.get_message();
448 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 42, formatter.str(), __FILE__, __LINE__ );
453 // access log flag and access log file name setting contents check.
454 if( element.access_log_flag == 1 && element.access_log_file_name == "" ) {
455 boost::format formatter("access log file name not set error");
456 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 3, formatter.str(), __FILE__, __LINE__ );
457 err.setter( true, "access log file name not set error" );
461 logger_implement_access *access_log_instance = NULL;
462 // access log instance create.
463 if( element.access_log_file_name != "" ) {
465 = logger_access_manager::getInstance().find_logger_implement_access(
466 element.access_log_file_name,
467 element.access_log_rotate_arguments,
469 if( access_log_instance == NULL ) {
470 boost::format formatter("access logger Instance acquisition err = %s, err.message = %s ");
471 formatter % ( err ? "true" : "false") % err.get_message();
472 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 4, formatter.str(), __FILE__, __LINE__ );
473 err.setter( true, "access log class instance create failed" );
479 boost::asio::ip::address address = element.tcp_accept_endpoint.address();
480 #ifdef SCHED_SETAFFINITY
481 vsnic_cpumask = get_cpu_mask( address );
482 rsnic_cpumask = get_cpu_mask( param_data.nic_realserver_side );
486 boost::system::error_code acceptor_err;
487 acceptor_.open( element.tcp_accept_endpoint.protocol(), acceptor_err );
489 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 5, acceptor_err.message(), __FILE__, __LINE__ );
490 err.setter( true, acceptor_err.message() );
493 acceptor_.set_option( boost::asio::ip::tcp::acceptor::reuse_address( true ), acceptor_err );
495 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 6, acceptor_err.message(), __FILE__, __LINE__ );
496 err.setter( true, acceptor_err.message() );
499 if( likely(address.is_v6()) ) {
500 boost::asio::ip::v6_only option(true);
501 acceptor_.set_option( option, acceptor_err );
503 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 7, acceptor_err.message(), __FILE__, __LINE__ );
504 err.setter( true, acceptor_err.message() );
508 acceptor_.bind( element.tcp_accept_endpoint, acceptor_err );
510 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 8, acceptor_err.message(), __FILE__, __LINE__ );
511 err.setter( true, acceptor_err.message() );
515 //read replication data
516 read_replicationdata();
518 //load protocol module
519 protomod = protocol_module_control::getInstance().load_module( element.protocol_module_name );
520 if( NULL == protomod ){
522 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 9, PROTOMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
523 err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
524 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
525 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
526 "l7vs::error_code& err ) : err = %s, err.message = %s");
527 formatter % ( err ? "true" : "false") % err.get_message();
528 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 43, formatter.str(), __FILE__, __LINE__ );
532 //Protocol Module Initialize
533 protomod->init_logger_functions(
534 boost::bind( &Logger::getLogLevel, LOG_CAT_PROTOCOL ),
535 boost::bind( &Logger::putLogFatal, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
536 boost::bind( &Logger::putLogError, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
537 boost::bind( &Logger::putLogWarn, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
538 boost::bind( &Logger::putLogInfo, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
539 boost::bind( &Logger::putLogDebug, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ) );
540 protomod->initialize(
541 boost::bind( &virtualservice_tcp::rs_list_begin, this ),
542 boost::bind( &virtualservice_tcp::rs_list_end, this ),
543 boost::bind( &virtualservice_tcp::rs_list_next, this, _1 ),
544 boost::bind( &virtualservice_tcp::rs_list_lock, this ),
545 boost::bind( &virtualservice_tcp::rs_list_unlock, this ) );
546 protomod->init_replication_functions(
547 boost::bind( &virtualservice_tcp::replication_pay_memory, this, _1, _2 ),
548 boost::bind( &virtualservice_tcp::replication_area_lock, this, element.protocol_module_name ),
549 boost::bind( &virtualservice_tcp::replication_area_unlock, this, element.protocol_module_name ),
550 element.tcp_accept_endpoint,
551 element.udp_recv_endpoint );
552 tcp_schedule_func_type sched_rs_func = boost::bind( &virtualservice_tcp::schedule_rs, this, _1, _2, _3, _4, _5 );
553 protomod->register_schedule( sched_rs_func );
555 protocol_module_base::check_message_result pm_result;
557 pm_result = protomod->check_parameter( element.protocol_args );
558 if( !pm_result.flag ){
559 err.setter( true, "Protocol Module argument error." );
560 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
561 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
562 "l7vs::error_code& err ) : err = %s, err.message = %s");
563 formatter % ( err ? "true" : "false") % err.get_message();
564 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 44, formatter.str(), __FILE__, __LINE__ );
568 pm_result = protomod->set_parameter( element.protocol_args );
569 if( !pm_result.flag ){
570 err.setter( true, "Protocol Module argument error." );
571 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
572 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
573 "l7vs::error_code& err ) : err = %s, err.message = %s");
574 formatter % ( err ? "true" : "false") % err.get_message();
575 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 45, formatter.str(), __FILE__, __LINE__ );
580 protomod->get_option_info(protocol_module_for_indication_options);
581 element.protocol_module_for_indication_options = protocol_module_for_indication_options;
583 //load schedule module
584 schedmod = schedule_module_control::getInstance().load_module( element.schedule_module_name );
585 if( NULL == schedmod ){
587 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 10, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
588 err.setter( true, SCHEDMOD_LOAD_ERROR_MSG );
589 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
590 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
591 "l7vs::error_code& err ) : err = %s, err.message = %s");
592 formatter % ( err ? "true" : "false") % err.get_message();
593 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 46, formatter.str(), __FILE__, __LINE__ );
597 //Schedule Module Initialize
598 schedmod->init_logger_functions(
599 boost::bind( &Logger::getLogLevel, LOG_CAT_SCHEDULE ),
600 boost::bind( &Logger::putLogFatal, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
601 boost::bind( &Logger::putLogError, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
602 boost::bind( &Logger::putLogWarn, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
603 boost::bind( &Logger::putLogInfo, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
604 boost::bind( &Logger::putLogDebug, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ) );
605 schedmod->initialize();
606 schedmod->init_replication_functions(
607 boost::bind( &virtualservice_tcp::replication_pay_memory, this, _1, _2 ),
608 boost::bind( &virtualservice_tcp::replication_area_lock, this, element.schedule_module_name ),
609 boost::bind( &virtualservice_tcp::replication_area_unlock, this, element.schedule_module_name ),
610 element.tcp_accept_endpoint,
611 element.udp_recv_endpoint );
613 // access log flag set
614 access_log_flag = false;
615 if ( element.access_log_flag == 1 ) {
616 access_log_flag = true;
619 // access log rotation infomation set.
620 if ( element.access_log_rotate_key_info == "" ) {
621 element.access_log_rotate_key_info = "none";
622 element.access_log_rotate_verbose_info = logger_access_manager::getInstance().get_rotate_default_verbose_displayed_contents();
624 element.access_log_rotate_verbose_info = element.access_log_rotate_key_info;
626 access_log_file_name = element.access_log_file_name;
627 access_log_rotate_arguments = element.access_log_rotate_arguments;
630 ssl_virtualservice_mode_flag = false;
631 ssl_file_name = element.ssl_file_name;
632 if ( ssl_file_name != "" ) {
633 ssl_file_name = element.ssl_file_name;
635 if(unlikely(!get_ssl_parameter())) {
637 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 11, "get ssl parameter failed", __FILE__, __LINE__ );
638 err.setter( true, "get ssl parameter failed" );
641 // set SSL configuration
642 if(unlikely(!set_ssl_config())) {
644 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 12, "set ssl config failed", __FILE__, __LINE__ );
645 err.setter( true, "set ssl config failed" );
648 ssl_virtualservice_mode_flag = true;
654 //create session pool
656 for( int i = 0; i < param_data.session_pool_size; ++i ){
658 tcp_session* sess = new tcp_session(*this,
661 element.tcp_accept_endpoint,
662 ssl_virtualservice_mode_flag,
664 is_session_cache_use,
666 access_log_instance);
667 session_result_message result = sess->initialize();
668 if( result.flag == true ){
669 err.setter( result.flag, result.message );
670 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
671 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
672 "l7vs::error_code& err ) : err = %s, err.message = %s");
673 formatter % ( err ? "true" : "false") % err.get_message();
674 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 47, formatter.str(), __FILE__, __LINE__ );
678 session_thread_control* p_stc = new session_thread_control( sess, vsnic_cpumask, rsnic_cpumask, -1 );
679 while( !pool_sessions.push( p_stc ) ){}
681 catch( std::bad_alloc ex ){
683 LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "error, create session.", __FILE__, __LINE__ );
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, 48, formatter.str(), __FILE__, __LINE__ );
693 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
694 boost::format fmt1( "pool_session.size = %d" );
695 fmt1 % pool_sessions.size();
696 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 49, fmt1.str(), __FILE__, __LINE__ );
697 boost::format fmt2( "active_session.size = %d" );
698 fmt2 % active_sessions.size();
699 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 50, fmt2.str(), __FILE__, __LINE__ );
703 err.setter( false, "" );
705 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
706 boost::format formatter("out_function : void virtualservice_tcp::initialize( "
707 "l7vs::error_code& err ) : err = %s, err.message = %s");
708 formatter % ( err ? "true" : "false") % err.get_message();
709 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 51, formatter.str(), __FILE__, __LINE__ );
714 * finalize virtualservice(TCP)
719 void l7vs::virtualservice_tcp::finalize( l7vs::error_code& err ){
720 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
721 boost::format formatter("in_function : void virtualservice_tcp::finalize( "
722 "l7vs::error_code& err )");
723 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 52, formatter.str(), __FILE__, __LINE__ );
725 boost::format fmt1( "pool_session.size = %d" );
726 fmt1 % pool_sessions.size();
727 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 53, fmt1.str(), __FILE__, __LINE__ );
728 boost::format fmt2( "active_session.size = %d" );
729 fmt2 % active_sessions.size();
730 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 54, fmt2.str(), __FILE__, __LINE__ );
736 while(active_sessions.size()){
737 boost::this_thread::yield();
741 tcp_session* tmp_session = NULL;
742 session_thread_control* tmp_stc = NULL;
743 waiting_sessions.pop( tmp_session, tmp_stc );
748 if( likely( pool_sessions.push( tmp_stc ) ) )break;
752 //release sessions[i]->join();
753 while( !pool_sessions.empty() ){
754 session_thread_control* stc = pool_sessions.pop();
757 boost::mutex::scoped_lock upthread_wait( stc->get_upthread_mutex() );
758 boost::mutex::scoped_lock downthread_wait( stc->get_downthread_mutex() );
762 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
763 boost::format fmt( "join pool sessin : pool_sessions.size = %d" );
764 fmt % pool_sessions.size();
765 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 55, fmt.str(), __FILE__, __LINE__ );
769 //unload ProtocolModule
771 //finalize ProtocolModule
772 protomod->finalize();
773 //unload ProtocolModule
774 protocol_module_control::getInstance().unload_module( protomod );
777 //unload ScheduleModule
779 schedule_module_control::getInstance().unload_module( schedmod );
783 active_sessions.clear();
784 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
785 boost::format fmt1( "pool_session.size = %d" );
786 fmt1 % pool_sessions.size();
787 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 56, fmt1.str(), __FILE__, __LINE__ );
788 boost::format fmt2( "active_session.size = %d" );
789 fmt2 % active_sessions.size();
790 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 57, fmt2.str(), __FILE__, __LINE__ );
793 //clear replication_data
794 bool replication_status = true;
795 replication& rep_noconst = const_cast<replication&>( rep );
797 if( replication::REPLICATION_SINGLE != rep_noconst.get_status() ){
798 unsigned int rep_size = 0;
799 replication_header* rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
800 if( (rep_header_ptr == NULL) || (0 == rep_size) ){
801 err.setter( true, REP_BLOCK_SIZE_ERR_MSG );
802 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 6, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
803 replication_status = false;
807 if( ( rep_size * DATA_SIZE ) <
808 ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
809 err.setter( true, REP_AREA_SIZE_ERR_MSG );
810 Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 7, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
811 replication_status = false;
813 if( (NULL != rep_header_ptr) && (replication_status) ){
814 //lock replication area
815 rep_noconst.lock( REP_AREA_NAME );
817 rep_header_ptr->data_num = 0;
818 //unlock replication area
819 rep_noconst.unlock( REP_AREA_NAME );
823 vsd.release_virtual_service( element );
825 if( access_log_file_name != "" ) {
826 // erase access log instance.
827 logger_access_manager::getInstance().erase_logger_implement_access( access_log_file_name, err );
828 if ( unlikely(err) ) {
829 boost::format fmt( "access logger instance erase err:%s" );
830 fmt % err.get_message();
831 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 8,
833 __FILE__, __LINE__ );
837 err.setter( false, "" );
839 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
840 boost::format formatter("out_function : void virtualservice_tcp::finalize( "
841 "l7vs::error_code& err ) : err = %s, err.message = %s");
842 formatter % ( err ? "true" : "false") % err.get_message();
843 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 58, formatter.str(), __FILE__, __LINE__ );
849 * equal compare virtualservice(TCP)
851 * @param virtualservice_base
852 * @return bool ( true = equal )
854 bool l7vs::virtualservice_tcp::operator==( const l7vs::virtualservice_base& in ){
855 boost::format formatter("function : void virtualservice_tcp::operator==( "
856 "const l7vs::virtualservice_base& in )");
857 Logger funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 59, formatter.str(), __FILE__, __LINE__ );
859 virtualservice_base& vs = const_cast<virtualservice_base&>( in );
860 return ( ( element.tcp_accept_endpoint == vs.get_element().tcp_accept_endpoint )
861 && ( element.udpmode == vs.get_element().udpmode ) );
865 * not-equal compare virtualservice(TCP)
867 * @param virtualservice_base
868 * @return bool ( true = not-equal )
870 bool l7vs::virtualservice_tcp::operator!=( const l7vs::virtualservice_base& in ){
871 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
872 boost::format formatter("in/out_function : void virtualservice_tcp::operator!=( "
873 "const l7vs::virtualservice_base& in )");
874 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 60, formatter.str(), __FILE__, __LINE__ );
876 virtualservice_base& vs = const_cast<virtualservice_base&>( in );
877 return ( ( element.tcp_accept_endpoint != vs.get_element().tcp_accept_endpoint )
878 || ( element.udpmode != vs.get_element().udpmode ) );
882 * add VirtualService( not-imprement )
884 * @param virtualservice_element
888 void l7vs::virtualservice_tcp::set_virtualservice( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
889 err.setter( false, "" );
893 * edit VirtualService
895 * @param virtualservice_element
899 void l7vs::virtualservice_tcp::edit_virtualservice( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
900 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
901 boost::format formatter("in_function : void virtualservice_tcp::edit_virtualservice( "
902 "const l7vs::virtualservice_element& in,"
903 "l7vs::error_code& err ) : dump in ");
904 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 61, formatter.str(), __FILE__, __LINE__ );
907 virtualservice_element& elem = const_cast<virtualservice_element&>( in );
908 //繝代Λ繝。繝シ繧ソ縺祁irtualService縺ォ荳
\80閾エ縺吶k縺区、懈渊
909 //udpmode縺ィtcp_accept_endpoint縺ィprotocol_module_name縺御ク
\80閾エ縺吶k縺薙→
910 if( ( element.udpmode != elem.udpmode ) ||
911 ( element.tcp_accept_endpoint != elem.tcp_accept_endpoint ) ||
912 ( element.protocol_module_name != elem.protocol_module_name ) ){
913 err.setter( true, "Virtual Service does not exist." );
914 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
915 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
916 "const l7vs::virtualservice_element& in,"
917 "l7vs::error_code& err ) : err = %s, err.message = %s");
918 formatter % ( err ? "true" : "false") % err.get_message();
919 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 62, formatter.str(), __FILE__, __LINE__ );
924 //if change ScueduleModule Name, unload old ScheduleModule and load new ScheduleModule
925 if( ( element.schedule_module_name != elem.schedule_module_name ) && ( "" != elem.schedule_module_name ) ){
926 schedule_module_control::getInstance().unload_module( schedmod );
927 schedmod = schedule_module_control::getInstance().load_module( elem.schedule_module_name );
928 if( NULL == schedmod ){
930 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 13, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
931 err.setter( true, SCHEDMOD_LOAD_ERROR_MSG );
932 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
933 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
934 "const l7vs::virtualservice_element& in,"
935 "l7vs::error_code& err ) : err = %s, err.message = %s");
936 formatter % ( err ? "true" : "false") % err.get_message();
937 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 63, formatter.str(), __FILE__, __LINE__ );
941 element.schedule_module_name = elem.schedule_module_name;
944 //additional PM options(for protomod_url)
945 protocol_module_base::check_message_result result;
946 if( NULL != protomod ){
947 result = protomod->add_parameter( elem.protocol_args );
949 for( size_t i = 0; i < elem.protocol_args.size(); ++i ){
950 element.protocol_args.push_back( elem.protocol_args[i] );
953 err.setter( true, result.message );
954 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
955 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
956 "const l7vs::virtualservice_element& in,"
957 "l7vs::error_code& err ) : err = %s, err.message = %s");
958 formatter % ( err ? "true" : "false") % err.get_message();
959 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 64, formatter.str(), __FILE__, __LINE__ );
965 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 14, PROTOMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
966 err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
967 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
968 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
969 "const l7vs::virtualservice_element& in,"
970 "l7vs::error_code& err ) : err = %s, err.message = %s");
971 formatter % ( err ? "true" : "false") % err.get_message();
972 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 65, formatter.str(), __FILE__, __LINE__ );
979 if( ULLONG_MAX == elem.qos_upstream )
980 element.qos_upstream = 0ULL;
981 else if( 0ULL != elem.qos_upstream )
982 element.qos_upstream = elem.qos_upstream;
984 if( ULLONG_MAX == elem.qos_downstream )
985 element.qos_downstream = 0ULL;
986 else if( 0ULL != elem.qos_downstream )
987 element.qos_downstream = elem.qos_downstream;
988 //sorry_maxconnection;
989 if( LLONG_MAX == elem.sorry_maxconnection )
990 element.sorry_maxconnection = 0;
991 else if( 0 != elem.sorry_maxconnection )
992 element.sorry_maxconnection = elem.sorry_maxconnection;
994 if( INT_MAX == elem.sorry_flag )
995 element.sorry_flag = 0;
996 else if( 0 != elem.sorry_flag )
997 element.sorry_flag = 1;
999 //if endpoint of SorryServer equal 255.255.255.255:0,not update
1000 //if equal endpoint 255.255.255.255:0, clear sorry parameters
1001 if( elem.sorry_endpoint ==
1002 boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "255.255.255.255" ), (0)) ){
1003 element.sorry_endpoint = boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "0.0.0.0" ), (0) );
1004 element.sorry_maxconnection = 0LL;
1005 element.sorry_flag = false;
1006 active_sessions.do_all( boost::bind( &session_thread_control::session_sorry_disable, _1 ) );
1008 if( elem.sorry_endpoint !=
1009 boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "0.0.0.0" ), (0) ) )
1010 element.sorry_endpoint = elem.sorry_endpoint;
1012 active_sessions.do_all( boost::bind( &session_thread_control::session_sorry_mode_change, _1, elem.sorry_flag ) );
1015 // access log flag ON and access log filename not set.
1016 if ( elem.access_log_flag == 1 && element.access_log_file_name == "" ) {
1018 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 15, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
1019 err.setter( true, "access log flag change err." );
1023 // access log flag check and send access log output ON or OFF message to tcp_session
1024 element.access_log_flag = elem.access_log_flag;
1025 if (elem.access_log_flag==1 && access_log_flag==false ) {
1026 active_sessions.do_all( boost::bind( &session_thread_control::session_accesslog_output_mode_on, _1 ) );
1027 access_log_flag = true;
1028 } else if ( elem.access_log_flag==0 && access_log_flag==true ) {
1029 active_sessions.do_all( boost::bind( &session_thread_control::session_accesslog_output_mode_off, _1 ) );
1030 access_log_flag = false;
1033 err.setter( false, "" );
1035 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1036 boost::format formatter("out_function : void virtualservice_tcp::set_virtualservice( "
1037 "const l7vs::virtualservice_element& in,"
1038 "l7vs::error_code& err ) : err = %s, err.message = %s");
1039 formatter % ( err ? "true" : "false") % err.get_message();
1040 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 66, formatter.str(), __FILE__, __LINE__ );
1047 * @param virtualservice_element
1051 void l7vs::virtualservice_tcp::add_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1052 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1053 boost::format formatter("in_function : void virtualservice_tcp::add_realserver( "
1054 "const l7vs::virtualservice_element& in,"
1055 "l7vs::error_code& err )");
1056 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 67, formatter.str(), __FILE__, __LINE__ );
1059 virtualservice_element& in_element = const_cast<virtualservice_element&>( in );
1061 //check equal virtualservice
1062 if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1063 err.setter( true, "Virtual Service does not exist." );
1064 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1065 boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
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, 68, formatter.str(), __FILE__, __LINE__ );
1074 if( in.realserver_vector.size() == 0U ){
1075 err.setter( true, "." );
1076 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1077 boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1078 "const l7vs::virtualservice_element& in,"
1079 "l7vs::error_code& err ) : err = %s, err.message = %s");
1080 formatter % ( err ? "true" : "false") % err.get_message();
1081 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 69, formatter.str(), __FILE__, __LINE__ );
1085 //lock rs_list_ref_count_inc_mutex
1086 rw_scoped_lock inc_lock( rs_list_ref_count_inc_mutex );
1088 //waiting, rs_list_ref_count become 0
1089 boost::xtime interval;
1091 boost::condition cond;
1093 interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1094 boost::mutex::scoped_lock lk( mtx );
1095 while( rs_list_ref_count != 0ULL ){
1096 cond.timed_wait( lk, interval );
1099 //check duplication realserver
1100 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1101 itr != in_element.realserver_vector.end();
1103 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1104 rs_itr != rs_list.end(); ++rs_itr ){
1105 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1106 err.setter( true, "Real Server already exist." );
1107 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1108 boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1109 "const l7vs::virtualservice_element& in,"
1110 "l7vs::error_code& err ) : err = %s, err.message = %s");
1111 formatter % ( err ? "true" : "false") % err.get_message();
1112 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 70, formatter.str(), __FILE__, __LINE__ );
1119 //pause active sessions
1120 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1123 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1124 itr != in_element.realserver_vector.end();
1127 rs.tcp_endpoint = itr->tcp_endpoint;
1128 rs.udp_endpoint = itr->udp_endpoint;
1129 rs.weight = itr->weight;
1130 rs_list.push_back( rs );
1133 //run active sessions
1134 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1136 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1137 boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1138 "const l7vs::virtualservice_element& in,"
1139 "l7vs::error_code& err ) : err = %s, err.message = %s");
1140 formatter % ( err ? "true" : "false") % err.get_message();
1141 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 71, formatter.str(), __FILE__, __LINE__ );
1148 * @param virtualservice_element
1152 void l7vs::virtualservice_tcp::edit_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1153 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1154 boost::format formatter("in_function : void virtualservice_tcp::edit_realserver( "
1155 "const l7vs::virtualservice_element& in,"
1156 "l7vs::error_code& err )");
1157 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 72, formatter.str(), __FILE__, __LINE__ );
1159 //check equal virtualservice
1160 if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1161 err.setter( true, "Virtual Service does not exist." );
1162 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1163 boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1164 "const l7vs::virtualservice_element& in,"
1165 "l7vs::error_code& err ) : err = %s, err.message = %s");
1166 formatter % ( err ? "true" : "false") % err.get_message();
1167 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 73, formatter.str(), __FILE__, __LINE__ );
1172 //lock rs_list_ref_count_inc_mutex
1173 rw_scoped_lock inc_lock( rs_list_ref_count_inc_mutex );
1175 //waiting, rs_list_ref_count become 0
1176 boost::xtime interval;
1178 boost::condition cond;
1180 interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1181 boost::mutex::scoped_lock lk( mtx );
1182 while( rs_list_ref_count != 0ULL ){
1183 cond.timed_wait( lk, interval );
1186 virtualservice_element& in_element = const_cast<virtualservice_element&>( in );
1188 //check is exist realserver
1189 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1190 itr != in_element.realserver_vector.end();
1192 bool exist_flag = false;
1193 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1194 rs_itr != rs_list.end(); ++rs_itr ){
1195 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1200 err.setter( true, "Real Server does not exist." );
1201 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1202 boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1203 "const l7vs::virtualservice_element& in,"
1204 "l7vs::error_code& err ) : err = %s, err.message = %s");
1205 formatter % ( err ? "true" : "false") % err.get_message();
1206 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 74, formatter.str(), __FILE__, __LINE__ );
1212 //pause active sessions
1213 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1216 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1217 itr != in_element.realserver_vector.end();
1219 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1220 rs_itr != rs_list.end(); ++rs_itr ){
1221 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1222 rs_itr->udp_endpoint = itr->udp_endpoint;
1224 if( itr->weight != -1 ) {
1225 rs_itr->weight = itr->weight;
1232 //run active sessions
1233 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1235 err.setter( false, "" );
1236 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1237 boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1238 "const l7vs::virtualservice_element& in,"
1239 "l7vs::error_code& err ) : err = %s, err.message = %s");
1240 formatter % ( err ? "true" : "false") % err.get_message();
1241 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 75, formatter.str(), __FILE__, __LINE__ );
1248 * @param virtualservice_element
1252 void l7vs::virtualservice_tcp::del_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1253 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1254 boost::format formatter("in_function : void virtualservice_tcp::del_realserver( "
1255 "const l7vs::virtualservice_element& in,"
1256 "l7vs::error_code& err )");
1257 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 76, formatter.str(), __FILE__, __LINE__ );
1260 //check equal virtualservice
1261 if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1262 err.setter( true, "Virtual Service is not equal." );
1263 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1264 boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1265 "const l7vs::virtualservice_element& in,"
1266 "l7vs::error_code& err ) : err = %s, err.message = %s");
1267 formatter % ( err ? "true" : "false") % err.get_message();
1268 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 77, formatter.str(), __FILE__, __LINE__ );
1273 //lock rs_list_ref_count_inc_mutex
1274 rw_scoped_lock inc_lock( rs_list_ref_count_inc_mutex );
1276 //waiting, rs_list_ref_count become 0
1277 boost::xtime interval;
1279 boost::condition cond;
1281 interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1282 boost::mutex::scoped_lock lk( mtx );
1283 while( rs_list_ref_count != 0ULL ){
1284 cond.timed_wait( lk, interval );
1287 virtualservice_element& in_element = const_cast<virtualservice_element&>( in );
1289 //check is exist realserver
1290 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1291 itr != in_element.realserver_vector.end();
1293 bool exist_flag = false;
1294 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1295 rs_itr != rs_list.end(); ++rs_itr ){
1296 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1301 err.setter( true, "Real Server does not exist." );
1302 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1303 boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1304 "const l7vs::virtualservice_element& in,"
1305 "l7vs::error_code& err ) : err = %s, err.message = %s");
1306 formatter % ( err ? "true" : "false") % err.get_message();
1307 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 78, formatter.str(), __FILE__, __LINE__ );
1313 //pause active sessions
1314 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1317 for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1318 itr != in_element.realserver_vector.end();
1320 for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1321 rs_itr != rs_list.end(); ++rs_itr ){
1322 if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1323 rs_list.erase( rs_itr );
1329 //run active sessions
1330 active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1332 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1333 boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1334 "const l7vs::virtualservice_element& in,"
1335 "l7vs::error_code& err ) : err = %s, err.message = %s");
1336 formatter % ( err ? "true" : "false") % err.get_message();
1337 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 79, formatter.str(), __FILE__, __LINE__ );
1342 * main loop of virtualservice(TCP)
1347 void l7vs::virtualservice_tcp::run(){
1348 Logger funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function : void virtualservice_tcp::run()", __FILE__, __LINE__ );
1350 if( pool_sessions.size() == 0 ){
1351 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.", __FILE__, __LINE__ );
1354 boost::asio::socket_base::receive_buffer_size option(8192 * 192);
1355 acceptor_.set_option(option);
1356 //set socket option TCP_DEFER_ACCEPT
1357 if(defer_accept_opt){
1358 boost::system::error_code ec;
1359 size_t len = sizeof(defer_accept_val);
1360 boost::asio::detail::socket_ops::setsockopt(acceptor_.native(),IPPROTO_TCP,TCP_DEFER_ACCEPT,&defer_accept_val,len,ec);
1363 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 17, "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__ );
1369 //switch active a session
1370 session_thread_control* stc_ptr;
1372 stc_ptr = pool_sessions.pop();
1376 //regist accept event handler
1377 waiting_sessions.insert( stc_ptr->get_session().get(), stc_ptr );
1379 if (!ssl_virtualservice_mode_flag) {
1380 acceptor_.async_accept( stc_ptr->get_session()->get_client_socket(),
1381 boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr, boost::asio::placeholders::error ) );
1383 acceptor_.async_accept( stc_ptr->get_session()->get_client_ssl_socket().lowest_layer(),
1384 boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr, boost::asio::placeholders::error ) );
1386 //regist timer event handler
1387 calc_bps_timer->expires_from_now( boost::posix_time::milliseconds( param_data.bps_interval ) );
1388 calc_bps_timer->async_wait( boost::bind( &virtualservice_tcp::handle_throughput_update,
1389 this, boost::asio::placeholders::error ) );
1391 //register handle_replication_interrupt
1392 replication_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1393 replication_timer->async_wait( boost::bind( &virtualservice_tcp::handle_replication_interrupt,
1394 this, boost::asio::placeholders::error ) );
1395 //register handle_protomod_replication
1396 protomod_rep_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1397 protomod_rep_timer->async_wait( boost::bind( &virtualservice_tcp::handle_protomod_replication,
1398 this, boost::asio::placeholders::error ) );
1399 //register handle_schedmod_replication
1400 schedmod_rep_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1401 schedmod_rep_timer->async_wait( boost::bind( &virtualservice_tcp::handle_schedmod_replication,
1402 this, boost::asio::placeholders::error ) );
1404 //run dispatcher(start io_service loop)
1407 //stop all active sessions
1409 active_sessions.do_all( boost::bind( &session_thread_control::session_stop, _1 ) );
1419 void l7vs::virtualservice_tcp::stop(){
1420 Logger funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function : void virtualservice_tcp::stop()", __FILE__, __LINE__ );
1422 boost::system::error_code err;
1424 acceptor_.close( err );
1426 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__ );
1434 * increment active-connection count
1439 void l7vs::virtualservice_tcp::connection_active( const boost::asio::ip::tcp::endpoint& in ){
1440 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1441 boost::format formatter("in_function : void virtualservice_tcp::connection_active( "
1442 "const boost::asio::ip::tcp::endpoint& in ) : in = %s");
1444 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__ );
1447 for( std::list<realserver>::iterator itr = rs_list.begin();
1448 itr != rs_list.end();
1450 if( itr->tcp_endpoint == in ){
1451 itr->increment_active();
1458 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1459 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 83, "out_function : void virtualservice_tcp::connection_active()", __FILE__, __LINE__ );
1464 * increment in-active-connection (and decrement active-connection count)
1469 void l7vs::virtualservice_tcp::connection_inactive( const boost::asio::ip::tcp::endpoint& in ){
1470 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1471 boost::format formatter("in_function : void virtualservice_tcp::connection_inactive( "
1472 "const boost::asio::ip::tcp::endpoint& in ) : in = %s");
1474 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__ );
1477 for( std::list<realserver>::iterator itr = rs_list.begin();
1478 itr != rs_list.end();
1480 if( itr->tcp_endpoint == in ){
1481 itr->decrement_active();
1482 itr->increment_inact();
1489 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1490 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 85, "out_function : void virtualservice_tcp::connection_inactive()", __FILE__, __LINE__ );
1500 void l7vs::virtualservice_tcp::release_session( const tcp_session* session_ptr ){
1501 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1502 boost::format funclog_fmt("in_function : void virtualservice_tcp::release_session( "
1503 "const tcp_session* session_ptr ) : session_ptr = %d");
1504 funclog_fmt % session_ptr;
1505 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 86, funclog_fmt.str(), __FILE__, __LINE__ );
1508 session_thread_control* stc_ptr = active_sessions.find( session_ptr );
1509 if( unlikely( NULL == stc_ptr ) ){
1510 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1511 boost::format fmt( "session release fail : active_sessions.find( const tcp_session* session_ptr = %d )");
1513 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 87, fmt.str(), __FILE__, __LINE__ );
1514 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 88, "out_function : void virtualservice_tcp::release_session( const boost::thread::id thread_id )", __FILE__, __LINE__ );
1519 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1520 boost::format fmt1( "pool_session.size = %d" );
1521 fmt1 % pool_sessions.size();
1522 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 89, fmt1.str(), __FILE__, __LINE__ );
1523 boost::format fmt2( "active_session.size = %d" );
1524 fmt2 % active_sessions.size();
1525 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 90, fmt2.str(), __FILE__, __LINE__ );
1526 boost::format fmt3( "active_count = %d" );
1527 fmt3 % active_count.get();
1528 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 91, fmt3.str(), __FILE__, __LINE__ );
1530 active_sessions.erase( session_ptr );
1531 stc_ptr->get_session()->initialize();
1533 if( likely( pool_sessions.push( stc_ptr ) ) ){
1538 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1539 boost::format fmt1( "pool_session.size = %d" );
1540 fmt1 % pool_sessions.size();
1541 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 92, fmt1.str(), __FILE__, __LINE__ );
1542 boost::format fmt2( "active_session.size = %d" );
1543 fmt2 % active_sessions.size();
1544 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 93, fmt2.str(), __FILE__, __LINE__ );
1545 boost::format fmt3( "active_count = %d" );
1546 fmt3 % active_count.get();
1547 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 94, fmt3.str(), __FILE__, __LINE__ );
1549 boost::format funclog_fmt("out_function : void virtualservice_tcp::release_session( "
1550 "const tcp_session* session_ptr ) : session_ptr = %d");
1551 funclog_fmt % session_ptr;
1552 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 95, funclog_fmt.str(), __FILE__, __LINE__ );
1557 // set_socket_option
1559 void l7vs::virtualservice_tcp::set_socket_option(){
1561 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1562 boost::format funclog_fmt("in_function : void virtualservice_tcp::et_socket_option");
1563 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 96, funclog_fmt.str(), __FILE__, __LINE__ );
1566 // socket option check & set
1567 //! is set option TCP_DEFER_ACCEPT
1568 defer_accept_opt = false;
1569 //! TCP_DEFER_ACCEPT option value
1570 defer_accept_val = 0;
1572 //! TCP_NODELAY (false:not set,true:set option)
1573 set_sock_opt.nodelay_opt = false;
1574 //! TCP_NODELAY option value (false:off,true:on)
1575 set_sock_opt.nodelay_val = false;
1576 //! TCP_CORK (false:not set,true:set option)
1577 set_sock_opt.cork_opt = false;
1578 //! TCP_CORK option value (false:off,true:on)
1579 set_sock_opt.cork_val = false;
1580 //! TCP_QUICKACK (false:not set,true:set option)
1581 set_sock_opt.quickack_opt = false;
1582 //! TCP_QUICKACK option value (false:off,true:on)
1583 set_sock_opt.quickack_val = false;
1585 // set socket option
1586 if ( element.socket_option_tcp_defer_accept != 0 ) {
1587 defer_accept_opt = true;
1588 if ( element.socket_option_tcp_defer_accept == 1 ) {
1589 defer_accept_val = 1;
1593 if ( element.socket_option_tcp_nodelay != 0 ) {
1594 set_sock_opt.nodelay_opt = true;
1595 if ( element.socket_option_tcp_nodelay == 1 ) {
1596 set_sock_opt.nodelay_val = true;
1600 if ( element.socket_option_tcp_cork != 0 ) {
1601 set_sock_opt.cork_opt = true;
1602 if ( element.socket_option_tcp_cork == 1 ) {
1603 set_sock_opt.cork_val = true;
1607 if ( element.socket_option_tcp_quickack != 0 ) {
1609 set_sock_opt.quickack_opt = true;
1610 if ( element.socket_option_tcp_quickack == 1 ) {
1611 set_sock_opt.quickack_val = true;
1615 //----Debug log----------------------------------------------------------------------
1616 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1617 boost::format formatter("set_socket_option"
1618 " defer_accept_opt[%s] defer_accept_val[%d]"
1619 " nodelay_opt[%s] nodelay_val[%s]"
1620 " cork_opt[%s] cork_val[%s]"
1621 " quickack_opt[%s]" "quickack_val[%s]");
1622 formatter %(defer_accept_opt ? "true" : "false") %defer_accept_val
1623 %(set_sock_opt.nodelay_opt ? "true" : "false") %(set_sock_opt.nodelay_val ? "true" : "false")
1624 %(set_sock_opt.cork_opt ? "true" : "false") %(set_sock_opt.cork_val ? "true" : "false")
1625 %(set_sock_opt.quickack_opt ? "true" : "false") %(set_sock_opt.quickack_val ? "true" : "false");
1626 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 97, formatter.str(), __FILE__, __LINE__ );
1628 //----Debug log----------------------------------------------------------------------
1633 //! get private key file password (for callback function)
1634 //! @return password string
1635 std::string l7vs::virtualservice_tcp::get_ssl_password()
1637 //*-------- DEBUG LOG --------*/
1638 if (unlikely(LOG_LV_DEBUG ==
1639 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1640 std::stringstream buf;
1641 buf << "in_function : ";
1642 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password()";
1643 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 98, buf.str(),
1644 __FILE__, __LINE__ );
1646 //*------ DEBUG LOG END ------*/
1648 // Get password from file.
1649 std::string retstr = "";
1651 char buf[MAX_SSL_PASSWD_SIZE + 3];
1652 if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1654 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1655 "Password file cannot open.", __FILE__, __LINE__ );
1657 if (fgets(buf, MAX_SSL_PASSWD_SIZE + 3, fp) == NULL) {
1658 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
1659 "Password not found in file.",
1660 __FILE__, __LINE__ );
1662 if ( strlen(buf) > MAX_SSL_PASSWD_SIZE ) {
1663 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1664 "Password is too long.",
1665 __FILE__, __LINE__ );
1667 buf[strlen(buf) - 1] = '\0';
1674 //*-------- DEBUG LOG --------*/
1675 if (unlikely(LOG_LV_DEBUG ==
1676 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1677 std::stringstream buf;
1678 buf << "out_function : ";
1679 buf << "std::string l7vs::virtualservice_tcp::get_ssl_password() : ";
1680 buf << "retstr = " << retstr;
1681 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 99, buf.str(),
1682 __FILE__, __LINE__ );
1684 //*------ DEBUG LOG END ------*/
1690 //! Convert verify option string to intger(#define).
1692 //! @param[in] opt_string option string
1693 //! @retval ret option value
1694 //! @retval -1 no match
1695 int l7vs::virtualservice_tcp::conv_verify_option(std::string opt_string)
1697 //*-------- DEBUG LOG --------*/
1698 if (unlikely(LOG_LV_DEBUG ==
1699 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1700 std::stringstream buf;
1701 buf << "in_function : ";
1702 buf << "int virtualservice_tcp::conv_verify_option";
1703 buf << "(std::string opt_string) : ";
1704 buf << "opt_string = " << opt_string;
1705 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 100, buf.str(),
1706 __FILE__, __LINE__ );
1708 //*------ DEBUG LOG END ------*/
1712 // /usr/include/openssl/ssl.h
1713 // #define SSL_VERIFY_NONE 0x00
1714 // #define SSL_VERIFY_PEER 0x01
1715 // #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
1716 // #define SSL_VERIFY_CLIENT_ONCE 0x04
1718 if (opt_string == "SSL_VERIFY_NONE") {
1719 ret = SSL_VERIFY_NONE;
1720 } else if (opt_string == "SSL_VERIFY_PEER") {
1721 ret = SSL_VERIFY_PEER;
1722 } else if (opt_string == "SSL_VERIFY_FAIL_IF_NO_PEER_CERT") {
1723 ret = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1724 } else if (opt_string == "SSL_VERIFY_CLIENT_ONCE") {
1725 ret = SSL_VERIFY_CLIENT_ONCE;
1727 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
1728 "verify option string no match.",
1729 __FILE__, __LINE__ );
1732 //*-------- DEBUG LOG --------*/
1733 if (unlikely(LOG_LV_DEBUG ==
1734 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1735 std::stringstream buf;
1736 buf << "out_function : ";
1737 buf << "int virtualservice_tcp::conv_verify_option";
1738 buf << "(std::string opt_string) : ";
1739 buf << "return_value = " << ret;
1740 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 101, buf.str(),
1741 __FILE__, __LINE__ );
1743 //*------ DEBUG LOG END ------*/
1744 // if ret == -1 then No match.
1749 // Convert SSL option string to intger(#define).
1751 // @param[in] opt_string option string
1752 // @retval ret option value
1753 // @retval -1 no match
1754 long int l7vs::virtualservice_tcp::conv_ssl_option(std::string opt_string)
1756 //*-------- DEBUG LOG --------*/
1757 if (unlikely(LOG_LV_DEBUG ==
1758 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1759 std::stringstream buf;
1760 buf << "in_function : ";
1761 buf << "long int virtualservice_tcp::conv_ssl_option";
1762 buf << "(std::string opt_string) : ";
1763 buf << "opt_string = " << opt_string;
1764 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 102, buf.str(),
1765 __FILE__, __LINE__ );
1767 //*------ DEBUG LOG END ------*/
1771 // /usr/include/openssl/ssl.h
1772 // #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
1773 // #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
1774 // #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
1775 // #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
1776 // #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
1777 // #define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L
1778 // #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
1779 // #define SSL_OP_TLS_D5_BUG 0x00000100L
1780 // #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
1781 // #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L
1782 // #define SSL_OP_ALL 0x00000FF7L
1783 // #define SSL_OP_NO_QUERY_MTU 0x00001000L
1784 // #define SSL_OP_COOKIE_EXCHANGE 0x00002000L
1785 // #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
1786 // #define SSL_OP_SINGLE_ECDH_USE 0x00080000L
1787 // #define SSL_OP_SINGLE_DH_USE 0x00100000L
1788 // #define SSL_OP_EPHEMERAL_RSA 0x00200000L
1789 // #define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
1790 // #define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
1791 // #define SSL_OP_NO_SSLv2 0x01000000L
1792 // #define SSL_OP_NO_SSLv3 0x02000000L
1793 // #define SSL_OP_NO_TLSv1 0x04000000L
1794 // #define SSL_OP_PKCS1_CHECK_1 0x08000000L
1795 // #define SSL_OP_PKCS1_CHECK_2 0x10000000L
1796 // #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
1797 // #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
1798 if (opt_string == "SSL_OP_MICROSOFT_SESS_ID_BUG") {
1799 ret = SSL_OP_MICROSOFT_SESS_ID_BUG;
1800 } else if (opt_string == "SSL_OP_NETSCAPE_CHALLENGE_BUG") {
1801 ret = SSL_OP_NETSCAPE_CHALLENGE_BUG;
1802 } else if (opt_string == "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG") {
1803 ret = SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
1804 } else if (opt_string == "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG") {
1805 ret = SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
1806 } else if (opt_string == "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER") {
1807 ret = SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
1808 } else if (opt_string == "SSL_OP_MSIE_SSLV2_RSA_PADDING") {
1809 ret = SSL_OP_MSIE_SSLV2_RSA_PADDING;
1810 } else if (opt_string == "SSL_OP_SSLEAY_080_CLIENT_DH_BUG") {
1811 ret = SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
1812 } else if (opt_string == "SSL_OP_TLS_D5_BUG") {
1813 ret = SSL_OP_TLS_D5_BUG;
1814 } else if (opt_string == "SSL_OP_TLS_BLOCK_PADDING_BUG") {
1815 ret = SSL_OP_TLS_BLOCK_PADDING_BUG;
1816 } else if (opt_string == "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS") {
1817 ret = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
1818 } else if (opt_string == "SSL_OP_ALL") {
1819 // boost::asio::ssl::context::default_workarounds
1821 } else if (opt_string == "SSL_OP_NO_QUERY_MTU") {
1822 ret = SSL_OP_NO_QUERY_MTU;
1823 } else if (opt_string == "SSL_OP_COOKIE_EXCHANGE") {
1824 ret = SSL_OP_COOKIE_EXCHANGE;
1825 } else if (opt_string == "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION") {
1826 ret = SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
1827 } else if (opt_string == "SSL_OP_SINGLE_ECDH_USE") {
1828 ret = SSL_OP_SINGLE_ECDH_USE;
1829 } else if (opt_string == "SSL_OP_SINGLE_DH_USE") {
1830 // boost::asio::ssl::context::single_dh_use
1831 ret = SSL_OP_SINGLE_DH_USE;
1832 } else if (opt_string == "SSL_OP_EPHEMERAL_RSA") {
1833 ret = SSL_OP_EPHEMERAL_RSA;
1834 } else if (opt_string == "SSL_OP_CIPHER_SERVER_PREFERENCE") {
1835 ret = SSL_OP_CIPHER_SERVER_PREFERENCE;
1836 } else if (opt_string == "SSL_OP_TLS_ROLLBACK_BUG") {
1837 ret = SSL_OP_TLS_ROLLBACK_BUG;
1838 } else if (opt_string == "SSL_OP_NO_SSLv2") {
1839 // boost::asio::ssl::context::no_sslv2
1840 ret = SSL_OP_NO_SSLv2;
1841 } else if (opt_string == "SSL_OP_NO_SSLv3") {
1842 // boost::asio::ssl::context::no_sslv3
1843 ret = SSL_OP_NO_SSLv3;
1844 } else if (opt_string == "SSL_OP_NO_TLSv1") {
1845 // boost::asio::ssl::context::no_tlsv1
1846 ret = SSL_OP_NO_TLSv1;
1847 } else if (opt_string == "SSL_OP_PKCS1_CHECK_1") {
1848 ret = SSL_OP_PKCS1_CHECK_1;
1849 } else if (opt_string == "SSL_OP_PKCS1_CHECK_2") {
1850 ret = SSL_OP_PKCS1_CHECK_2;
1851 } else if (opt_string == "SSL_OP_NETSCAPE_CA_DN_BUG") {
1852 ret = SSL_OP_NETSCAPE_CA_DN_BUG;
1853 } else if (opt_string == "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG") {
1854 ret = SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
1856 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
1857 "ssl option string no match.",
1858 __FILE__, __LINE__ );
1861 //*-------- DEBUG LOG --------*/
1862 if (unlikely(LOG_LV_DEBUG ==
1863 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1864 std::stringstream buf;
1865 buf << "out_function : ";
1866 buf << "long int virtualservice_tcp::conv_ssl_option";
1867 buf << "(std::string opt_string) : ";
1868 buf << "return_value = " << ret;
1869 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 103, buf.str(),
1870 __FILE__, __LINE__ );
1872 //------ DEBUG LOG END ------*/
1873 // if ret == -1 then No match.
1878 //! get ssl parameter
1879 //! @return get ssl parameter result
1880 bool l7vs::virtualservice_tcp::get_ssl_parameter()
1882 //*-------- DEBUG LOG --------*/
1883 if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1884 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 104,
1885 "in_function : bool virtualservice_tcp::get_ssl_parameter()",
1886 __FILE__, __LINE__ );
1888 //*------ DEBUG LOG END ------*/
1889 typedef std::vector< std::string > string_vector_type;
1892 string_vector_type string_vector;
1893 l7vs::error_code err;
1894 bool retbool = false;
1897 // param init ( ssl configuration file )
1898 if (unlikely(!param.init(l7vs::PARAM_COMP_SSL, ssl_file_name))) {
1899 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 24,
1900 "SSL config file read error.",
1901 __FILE__, __LINE__ );
1905 //// SSL context parameter
1906 // Get parameter "ca_dir".
1907 ca_dir = param.get_string(l7vs::PARAM_COMP_SSL, "ca_dir",
1908 err, ssl_file_name);
1909 if (unlikely(err) || ca_dir == "") {
1910 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 9,
1911 "ca_dir parameter not found. Use default value.",
1912 __FILE__, __LINE__ );
1913 ca_dir = DEFAULT_SSL_CA_DIR;
1916 // Get parameter "ca_file".
1917 ca_file = param.get_string(l7vs::PARAM_COMP_SSL, "ca_file",
1918 err, ssl_file_name);
1919 if (unlikely(err)) {
1920 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 25,
1921 "Cannot get ca_file parameter.",
1922 __FILE__, __LINE__ );
1926 // Get parameter "cert_chain_dir".
1927 cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
1931 if (unlikely(err) || cert_chain_dir == "") {
1932 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 10,
1933 "cert_chain_dir parameter not found. Use default value.",
1934 __FILE__, __LINE__ );
1935 cert_chain_dir = DEFAULT_SSL_CERT_CHAIN_DIR;
1938 // Get parameter "cert_chain_file".
1939 cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
1943 if (unlikely(err) || cert_chain_file == "") {
1944 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 26,
1945 "Cannot get cert_chain_file parameter.",
1946 __FILE__, __LINE__ );
1950 // Get parameter "private_key_dir".
1951 private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
1955 if (unlikely(err) || private_key_dir == "") {
1956 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 11,
1957 "private_key_dir parameter not found. Use default value.",
1958 __FILE__, __LINE__ );
1959 private_key_dir = DEFAULT_SSL_PRIVATE_KEY_DIR;
1962 // Get parameter "private_key_file".
1963 private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
1967 if (unlikely(err) || private_key_file == "") {
1968 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 27,
1969 "Cannot get private_key_file parameter.",
1970 __FILE__, __LINE__ );
1974 // Get parameter "private_key_filetype".
1975 // and convert string to filetype define value.
1977 // /usr/include/openssl/ssl.h
1978 // #define SSL_FILETYPE_PEM X509_FILETYPE_PEM ->1
1979 // #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 ->2
1982 std::string filetype_str = param.get_string(
1983 l7vs::PARAM_COMP_SSL,
1984 "private_key_filetype",
1987 if (unlikely(err) || filetype_str == "") {
1988 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 12,
1989 "private_key_filetype parameter not found. Use default value.",
1990 __FILE__, __LINE__ );
1991 private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
1992 } else if (filetype_str == "SSL_FILETYPE_PEM") {
1993 private_key_filetype = boost::asio::ssl::context::pem;
1994 } else if (filetype_str == "SSL_FILETYPE_ASN1") {
1995 private_key_filetype = boost::asio::ssl::context::asn1;
1997 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
1998 "private_key_filetype convert error.",
1999 __FILE__, __LINE__ );
2003 // Get parameter "private_key_passwd_dir".
2004 private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2005 "private_key_passwd_dir",
2008 if (unlikely(err) || private_key_passwd_dir == "") {
2009 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 13,
2010 "private_key_passwd_dir parameter not found. Use default value.",
2011 __FILE__, __LINE__ );
2012 private_key_passwd_dir = DEFAULT_SSL_PRIVATE_KEY_PASSWD_DIR;
2015 // Get parameter "private_key_passwd_file".
2016 private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2017 "private_key_passwd_file",
2020 if (unlikely(err) || private_key_passwd_file == "") {
2021 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
2022 "Cannot get private_key_passwd_file parameter.",
2023 __FILE__, __LINE__ );
2027 // Get parameter "verify_options".
2028 param.get_multistring(l7vs::PARAM_COMP_SSL,
2033 if (unlikely(err)) {
2034 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 14,
2035 "verify_options parameter not found. Use default value.",
2036 __FILE__, __LINE__ );
2037 verify_options = DEFAULT_SSL_VERIFY_OPTIONS;
2039 // Make verify option bit data.
2040 for (string_vector_type::iterator itr = string_vector.begin();
2041 itr != string_vector.end(); ++itr) {
2042 // Convert string to define value.
2043 int int_val = conv_verify_option(*itr);
2044 if (unlikely(int_val == -1)) {
2045 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 30,
2046 "verify_options convert error.",
2047 __FILE__, __LINE__ );
2050 verify_options = (verify_options | int_val);
2054 // Get parameter "verify_cert_depth".
2055 verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2056 "verify_cert_depth",
2059 if (unlikely(err)) {
2060 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 15,
2061 "verify_cert_depth parameter not found. Use default value.",
2062 __FILE__, __LINE__ );
2063 verify_cert_depth = DEFAULT_SSL_VERIFY_CERT_DEPTH;
2064 } else if (unlikely(verify_cert_depth < 0 ||
2065 verify_cert_depth > INT_MAX)) {
2066 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 31,
2067 "Invalid verify_cert_depth parameter value.",
2068 __FILE__, __LINE__ );
2072 // Get parameter "ssl_options".
2073 // and Check dh parameter file use or not.
2074 is_tmp_dh_use = false;
2075 param.get_multistring(l7vs::PARAM_COMP_SSL,
2080 if (unlikely(err)) {
2081 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 16,
2082 "ssl_options parameter not found. Use default value.",
2083 __FILE__, __LINE__ );
2084 ssl_options = DEFAULT_SSL_OPTIONS;
2085 is_tmp_dh_use = true;
2087 // Make ssl option bit data.
2088 for (string_vector_type::iterator itr = string_vector.begin();
2089 itr != string_vector.end(); ++itr) {
2090 // Convert string to define value.
2091 long int longint_val = conv_ssl_option(*itr);
2092 if (unlikely(longint_val == -1)) {
2093 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 32,
2094 "ssl_options convert error.",
2095 __FILE__, __LINE__ );
2097 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2098 is_tmp_dh_use = true;
2100 ssl_options = (ssl_options | longint_val);
2104 if (is_tmp_dh_use) {
2105 // Get parameter "tmp_dh_dir".
2106 tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2110 if (unlikely(err) || tmp_dh_dir == "") {
2111 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
2112 "tmp_dh_dir parameter not found. Use default value.",
2113 __FILE__, __LINE__ );
2114 tmp_dh_dir = DEFAULT_SSL_TMP_DH_DIR;
2116 // Get parameter "tmp_dh_file".
2117 tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2121 if (unlikely(err) || tmp_dh_file == "") {
2122 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 33,
2123 "Cannot get tmp_dh_file parameter.",
2124 __FILE__, __LINE__ );
2129 // Get parameter "cipher_list".
2130 cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2134 if (unlikely(err) || cipher_list == "") {
2135 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 18,
2136 "cipher_list parameter not found. Use default value.",
2137 __FILE__, __LINE__ );
2138 cipher_list = DEFAULT_SSL_CIPHER_LIST;
2141 //// SSL session cache parameter
2142 // Get parameter "session_cache".
2143 is_session_cache_use = false;
2144 std::string cache_str = param.get_string(l7vs::PARAM_COMP_SSL,
2148 if (unlikely(err) || cache_str == "") {
2149 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
2150 "session_cache parameter not found. Use default value.",
2151 __FILE__, __LINE__ );
2152 is_session_cache_use = true;
2153 } else if (cache_str == "on") {
2154 is_session_cache_use = true;
2155 } else if (cache_str == "off") {
2156 is_session_cache_use = false;
2158 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2159 "Invalid session_cache parameter value.",
2160 __FILE__, __LINE__ );
2164 if (is_session_cache_use) {
2165 session_cache_mode = DEFAULT_SSL_SESSION_CACHE_MODE;
2166 // Get parameter "session_cache_size".
2167 session_cache_size = param.get_int(l7vs::PARAM_COMP_SSL,
2168 "session_cache_size",
2171 if (unlikely(err)) {
2172 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
2173 "session_cache_size parameter not found. Use default value.",
2174 __FILE__, __LINE__ );
2175 session_cache_size = DEFAULT_SSL_SESSION_CACHE_SIZE;
2176 } else if (session_cache_size < 0 ||
2177 session_cache_size > INT_MAX) {
2178 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 35,
2179 "Invalid session_cache_size parameter value.",
2180 __FILE__, __LINE__ );
2183 // Get parameter "session_cache_timeout".
2184 session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2185 "session_cache_timeout",
2188 if (unlikely(err)) {
2189 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
2190 "session_cache_timeout parameter not found. Use default value.",
2191 __FILE__, __LINE__ );
2192 session_cache_timeout = DEFAULT_SSL_SESSION_CACHE_TIMEOUT;
2193 } else if (session_cache_timeout < 0 ||
2194 session_cache_timeout > INT_MAX) {
2195 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 36,
2196 "Invalid session_cache_timeout parameter value.",
2197 __FILE__, __LINE__ );
2201 session_cache_mode = SSL_SESS_CACHE_OFF;
2204 //// SSL handshake timer parameter
2205 // Get parameter "timeout_sec".
2206 handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2210 if (unlikely(err)) {
2211 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2212 "timeout_sec parameter not found. Use default value.",
2213 __FILE__, __LINE__ );
2214 handshake_timeout = DEFAULT_SSL_HANDSHAKE_TIMEOUT;
2215 } else if (handshake_timeout <= 0 || handshake_timeout > INT_MAX) {
2216 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 37,
2217 "Invalid timeout_sec parameter value.",
2218 __FILE__, __LINE__ );
2228 //*-------- DEBUG LOG --------*/
2229 if (unlikely(LOG_LV_DEBUG ==
2230 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2231 std::stringstream buf;
2232 buf<<"out_function : bool virtualservice_tcp::get_ssl_parameter() : ";
2233 buf<<"ca_dir = " << ca_dir << ", ";
2234 buf<<"ca_file = " << ca_file << ", ";
2235 buf<<"cert_chain_dir = " << cert_chain_dir << ", ";
2236 buf<<"cert_chain_file = " << cert_chain_file << ", ";
2237 buf<<"private_key_dir = " << private_key_dir << ", ";
2238 buf<<"private_key_file = " << private_key_file << ", ";
2239 buf<<"private_key_filetype = " << private_key_filetype << ", ";
2240 buf<<"private_key_passwd_dir = " << private_key_passwd_dir << ", ";
2241 buf<<"private_key_passwd_file = "<< private_key_passwd_file << ", ";
2242 buf<<"verify_options = " << verify_options << ", ";
2243 buf<<"verify_cert_depth = " << verify_cert_depth << ", ";
2244 buf<<"ssl_options = " << ssl_options << ", ";
2245 if (is_tmp_dh_use) {
2246 buf<< "tmp_dh_dir = " << tmp_dh_dir << ", ";
2247 buf<< "tmp_dh_file = " << tmp_dh_file << ", ";
2249 buf<<"cipher_list = " << cipher_list << ", ";
2250 buf<<"session_cache_mode = " << session_cache_mode << ", ";
2251 if (is_session_cache_use) {
2252 buf<<"session_cache_size = " << session_cache_size << ", ";
2253 buf<<"session_cache_timeout = "<< session_cache_timeout << ", ";
2255 buf<<"handshake_timeout = " << handshake_timeout;
2256 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2258 __FILE__, __LINE__ );
2260 //*------ DEBUG LOG END ------*/
2265 // set ssl context and ssl session cache configuration
2266 // @return set ssl config result
2267 bool l7vs::virtualservice_tcp::set_ssl_config()
2269 //*-------- DEBUG LOG --------*/
2270 if (unlikely(LOG_LV_DEBUG ==
2271 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2272 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 106,
2273 "in_function : bool virtualservice_tcp::set_ssl_config()",
2274 __FILE__, __LINE__ );
2276 //*------ DEBUG LOG END ------*/
2278 bool retbool = false;
2281 //// SSL context setting.
2283 if (ca_file.size() == 0) {
2284 // specified CA path.
2286 sslcontext.add_verify_path(ca_dir);
2287 } catch (std::exception& e) {
2288 std::stringstream buf;
2289 buf << "Set root CA path error : " << e.what() << ".";
2290 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 107,
2292 __FILE__, __LINE__ );
2296 // specified CA file.
2298 sslcontext.load_verify_file(ca_dir + ca_file);
2299 } catch (std::exception& e) {
2300 std::stringstream buf;
2301 buf << "Set root CA file error : " << e.what() << ".";
2302 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 108,
2304 __FILE__, __LINE__ );
2309 // Set certificate chain file.
2311 sslcontext.use_certificate_chain_file(
2312 cert_chain_dir + cert_chain_file);
2313 } catch (std::exception& e) {
2314 std::stringstream buf;
2315 buf << "Set certificate chain file error : " << e.what() << ".";
2316 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 109, buf.str(),
2317 __FILE__, __LINE__ );
2321 // Set password callback function.
2323 sslcontext.set_password_callback(
2324 boost::bind(&virtualservice_tcp::get_ssl_password, this));
2325 } catch (std::exception& e) {
2326 std::stringstream buf;
2327 buf << "Set password callback error : " << e.what() << ".";
2328 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 110, buf.str(),
2329 __FILE__, __LINE__ );
2333 // Set private key file and filetype.
2335 sslcontext.use_private_key_file(
2336 private_key_dir + private_key_file, private_key_filetype);
2337 } catch (std::exception& e) {
2338 std::stringstream buf;
2339 buf <<"Set private key file and filetype error : "<<e.what()<<".";
2340 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 111, buf.str(),
2341 __FILE__, __LINE__ );
2345 // Set verify options on the context.
2347 sslcontext.set_verify_mode(verify_options);
2348 } catch (std::exception& e) {
2349 std::stringstream buf;
2350 buf << "Set verify option error : " << e.what() << ".";
2351 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 112, buf.str(),
2352 __FILE__, __LINE__ );
2356 // Set verify depth on the context.
2357 SSL_CTX_set_verify_depth(sslcontext.impl(), verify_cert_depth);
2359 // Set SSL options on the context.
2361 sslcontext.set_options(ssl_options);
2362 } catch (std::exception& e) {
2363 std::stringstream buf;
2364 buf << "Set SSL option error : " << e.what() << ".";
2365 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 113, buf.str(),
2366 __FILE__, __LINE__ );
2370 // Set temporary Diffie-Hellman parameters file.
2371 if (is_tmp_dh_use) {
2373 sslcontext.use_tmp_dh_file(tmp_dh_dir + tmp_dh_file);
2374 } catch (std::exception& e) {
2375 std::stringstream buf;
2376 buf << "Set tmp DH file error : " << e.what() << ".";
2377 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 114,
2379 __FILE__, __LINE__ );
2385 // Set cipher list on the context.
2386 if (unlikely(SSL_CTX_set_cipher_list(sslcontext.impl(),
2387 cipher_list.c_str()) != 1)) {
2388 std::stringstream buf;
2389 buf << "Set cipher list error.";
2390 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 115,
2392 __FILE__, __LINE__ );
2396 //// SSL session cache setting.
2397 if (is_session_cache_use) {
2398 // Set session id context on the context.
2399 if (unlikely( SSL_CTX_set_session_id_context(
2401 (const unsigned char *)"ultramonkey", 11) != 1)) {
2402 std::stringstream buf;
2403 buf << "Set session id context error.";
2404 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 116,
2406 __FILE__, __LINE__ );
2410 // Set session cache mode on the context.
2411 SSL_CTX_set_session_cache_mode(
2412 sslcontext.impl(),session_cache_mode);
2414 // Set session cache size on the context.
2415 SSL_CTX_sess_set_cache_size(sslcontext.impl(), session_cache_size);
2417 // Set session cache timeout on the context.
2418 SSL_CTX_set_timeout(sslcontext.impl(), session_cache_timeout);
2421 // session cache OFF.
2422 SSL_CTX_set_session_cache_mode(sslcontext.impl(),
2423 SSL_SESS_CACHE_OFF);
2431 //*-------- DEBUG LOG --------*/
2432 if (unlikely(LOG_LV_DEBUG ==
2433 Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2434 std::stringstream buf;
2435 buf << "out_function : bool virtualservice_tcp::set_ssl_config() : ";
2436 get_ssl_config(buf);
2437 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 117, buf.str(),
2438 __FILE__, __LINE__ );
2440 //*------ DEBUG LOG END ------*/
2445 // flush ssl session
2446 void l7vs::virtualservice_tcp::flush_ssl_session()
2448 // check expired cached sessions and do flushing
2449 // Need ssl_context lock?
2450 SSL_CTX_flush_sessions(sslcontext.impl(), time(0));
2454 // get ssl configuration form ssl context. (for debug)
2455 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream& buf)
2457 buf<<"SSL configuration information : ";
2458 buf<<"Verify mode[" << SSL_CTX_get_verify_mode(sslcontext.impl()) << "] ";
2459 buf<<"Verify depth["<< SSL_CTX_get_verify_depth(sslcontext.impl())<< "] ";
2460 buf<<"SSL options[" << SSL_CTX_get_options(sslcontext.impl()) << "] ";
2461 buf<<"Cache mode[" << SSL_CTX_get_session_cache_mode(sslcontext.impl());
2463 buf<<"Cache size["<<SSL_CTX_sess_get_cache_size(sslcontext.impl())<< "] ";
2464 buf<<"Cache timeout[" << SSL_CTX_get_timeout(sslcontext.impl()) << "] ";
2468 // get ssl session cache information form ssl context. (for debug)
2469 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream& buf)
2471 buf << "SSL session cache information : ";
2472 buf << "Session number[" << SSL_CTX_sess_number(sslcontext.impl()) << "] ";
2473 buf << "Accept[" << SSL_CTX_sess_accept(sslcontext.impl()) << "] ";
2474 buf << "Accept good[" << SSL_CTX_sess_accept_good(sslcontext.impl()) << "] ";
2475 buf << "Accept renegotiate[" << SSL_CTX_sess_accept_renegotiate(sslcontext.impl()) << "] ";
2476 buf << "Hits[" << SSL_CTX_sess_hits(sslcontext.impl()) << "] ";
2477 buf << "Misses[" << SSL_CTX_sess_misses(sslcontext.impl()) << "] ";
2478 buf << "Timeouts[" << SSL_CTX_sess_timeouts(sslcontext.impl()) << "] ";
2479 buf << "Cache full[" << SSL_CTX_sess_cache_full(sslcontext.impl()) << "] ";