OSDN Git Service

07dcfb6c0d08cd1a0e05232534b354669fe43ad4
[ultramonkey-l7/ultramonkey-l7-v3.git] / l7vsd / src / virtualservice_tcp.cpp
1 /*!
2  *    @file    virtualservice_tcp.cpp
3  *    @brief    VirtualService class implementations for TCP
4  *
5  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
6  * Copyright (C) 2009  NTT COMWARE Corporation.
7  *
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.
12  *
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.
17  *
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
21  * 02110-1301 USA
22  *
23  **********************************************************************/
24
25 #include <vector>
26 #include <sstream>
27 #include <boost/date_time/posix_time/posix_time.hpp>
28 #include <boost/bind.hpp>
29 #include <boost/lexical_cast.hpp>
30 #include <boost/format.hpp>
31
32 #include "virtualservice.h"
33 #include "logger_enum.h"
34 #include "logger.h"
35 #include "parameter.h"
36
37 #include "utility.h"
38
39 #include "logger_access_manager.h"
40
41 // imprementation for virtualservice_tcp
42 /*!
43  * virtualservice_tcp class constructor.
44  */
45 l7vs::virtualservice_tcp::virtualservice_tcp(const l7vsd& invsd,
46                          const replication& inrep,
47                          const virtualservice_element& inelement )
48                          :
49                          virtualservice_base( invsd, inrep, inelement ),
50                          acceptor_( dispatcher ),
51                          sslcontext(dispatcher, DEFAULT_SSL_METHOD),
52                          access_log_file_name("")
53 {
54     active_count = 0;
55     
56     ca_dir = "";
57     ca_file = "";
58     cert_chain_dir = "";
59     cert_chain_file = "";
60     private_key_dir = "";
61     private_key_file = "";
62     private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
63     private_key_passwd_dir = "";
64     private_key_passwd_file = "";
65     verify_options = 0;
66     verify_cert_depth = 0;
67     ssl_options = 0;
68     is_tmp_dh_use = false;
69     tmp_dh_dir = "";
70     tmp_dh_file = "";
71     cipher_list = "";
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;
77
78 }
79 /*!
80  * virtualservice_tcp class destructor.
81  */
82 l7vs::virtualservice_tcp::~virtualservice_tcp(){
83 }
84
85 /*!
86  * replication interrupt event
87  *
88  * @param   err
89  * @return  void
90  */
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__ );
97     }
98
99     if( unlikely( err ) ){
100         //ERROR case
101         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, err.message(), __FILE__, __LINE__ );
102         return;
103     }
104
105     bool    newdata    = true;
106     replication&    rep_noconst = const_cast<replication&>( rep );
107
108     if( replication::REPLICATION_SINGLE == rep_noconst.get_status() ){
109         Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "replication mode is single.", __FILE__, __LINE__ );
110         return;
111     }
112
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;
119     
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__ );
125         return;
126     }
127
128     //check maxdatasize
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__ );
132         return;
133     }
134
135     //lock replication area
136     rep_noconst.lock( REP_AREA_NAME );
137
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 )
142         loop_cnt = 0;
143
144     //set start pointer(pointer of replication_data)
145     replication_data*    rep_data_ptr = reinterpret_cast<replication_data*>( ++rep_header_ptr );
146
147     //find vs(loop)
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 ) ) ){
152             newdata = false;
153             break;
154         }
155         //increment data pointer
156         ++rep_data_ptr;
157     }
158
159     //if it is new data, increment data num.
160     if( newdata ){
161         rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
162         ++(rep_header_ptr->data_num);
163     }
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;
173
174     //unlock replication area
175     rep_noconst.unlock( REP_AREA_NAME );
176
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 ) );
181
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__ );
184     }
185 }
186
187 /*!
188  * read replication data
189  *
190  * @param   read_replicationdata
191  * @param    error_code
192  * @return  void
193  */
194 void    l7vs::virtualservice_tcp::read_replicationdata(){
195     Logger    funclog( LOG_CAT_L7VSD_VIRTUALSERVICE, 22, "function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
196
197     replication&    rep_noconst = const_cast<replication&>( rep );
198
199     if( replication::REPLICATION_SINGLE == rep_noconst.get_status() ){
200         Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, "replication mode is single.", __FILE__, __LINE__ );
201         return;
202     }
203
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__ );
210         }
211         return;
212     }
213
214     //check maxdatasize
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__ );
220         }
221         return;
222     }
223     //lock replication area
224     rep_noconst.lock( REP_AREA_NAME );
225
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__ );
233         }
234         rep_header_ptr->data_num = 0;
235         rep_noconst.unlock( REP_AREA_NAME );
236         return;
237     }
238
239     //set start pointer(pointer of replication_data)
240     replication_data*    rep_data_ptr = reinterpret_cast<replication_data*>( ++rep_header_ptr );
241
242     //find vs(loop)
243     for( unsigned int i = 0; i < loop_cnt; ++i ){
244         //get tcp endpointdata
245         std::string        tmpstr = rep_data_ptr->tcp_endpoint;
246         std::string        ipaddr;
247         unsigned short    portno;
248         try{
249             portno    = boost::lexical_cast<unsigned short>( tmpstr.substr( (tmpstr.rfind( ":" )+1) ) );
250         }
251         catch( const boost::bad_lexical_cast& err ){
252             portno    = 0;
253         }
254         if( tmpstr[0] == '[' ){
255             //IPv6 endpoint
256             ipaddr    = tmpstr.substr( 1, (tmpstr.rfind( "]" )-1) );
257         }else{
258             //IPv4 endpoint
259             ipaddr    = tmpstr.substr( 0, tmpstr.rfind( ":" ) );
260         }
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;
266             try{
267                 portno    = boost::lexical_cast<unsigned short>( tmpstr.substr( (tmpstr.rfind( ":" )+1) ) );
268             }
269             catch( const boost::bad_lexical_cast& err ){
270                 portno    = 0;
271             }
272             if( tmpstr[0] == '[' ){
273                 //IPv6 endpoint
274                 ipaddr    = tmpstr.substr( 1, (tmpstr.rfind( "]" )-1) );
275             }else{
276                 //IPv4 endpoint
277                 ipaddr    = tmpstr.substr( 0, tmpstr.rfind( ":" ) );
278             }
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;
284             break;
285         }
286         //increment data pointer
287         ++rep_data_ptr;
288     }
289
290     //unlock replication area
291     rep_noconst.unlock( REP_AREA_NAME );
292
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__ );
295     }
296 }
297
298 /*!
299  * accept event
300  *
301  * @param   handle_accept
302  * @param    error_code
303  * @return  void
304  */
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__ );
312     }
313
314     session_thread_control*        stc_ptr_noconst = const_cast<session_thread_control*>( stc_ptr );
315
316     if( unlikely( err ) ){
317         //ERROR case
318         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, err.message(), __FILE__, __LINE__ );
319         return;
320     }
321
322     tcp_session*    tmp_session    = stc_ptr_noconst->get_session().get();
323
324     // ssl session cache flush
325     if( ( ssl_file_name != "" ) && ( is_session_cache_use == true ) ) {
326
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,
335                         buf.str(),
336                         __FILE__, __LINE__ );
337         }
338         //*------ DEBUG LOG END ------*/
339
340         long ssl_cache_num = SSL_CTX_sess_number(sslcontext.impl());
341         if ( ssl_cache_num >= session_cache_size ) {
342             flush_ssl_session();
343         }
344
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,
353                         buf.str(),
354                         __FILE__, __LINE__ );
355         }
356         //*------ DEBUG LOG END ------*/
357
358     }
359
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 );
362
363     active_sessions.insert( tmp_session, stc_ptr_noconst );
364
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__ );
373         }
374         stc_ptr_noconst->get_session()->set_virtual_service_message( tcp_session::SORRY_STATE_ENABLE );
375     }
376
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__ );
390     }
391
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() );
394
395     stc_ptr_noconst->startupstream();
396     stc_ptr_noconst->startdownstream();
397
398     //waiting, pool_sessions.size become over 1
399     //pick up session from pool
400     session_thread_control*        stc_ptr_register_accept;
401     do{
402         stc_ptr_register_accept = pool_sessions.pop();
403     }
404     while( unlikely( !stc_ptr_register_accept ) );
405
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() );
409
410     waiting_sessions.insert( stc_ptr_register_accept->get_session().get(), stc_ptr_register_accept );
411
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__ );
425     }
426
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 ) );
431     } else {
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 ) );
434     }
435
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__ );
438     }
439 }
440
441 /*!
442  * initialize virtualservice(TCP)
443  *
444  * @param   erro_code
445  * @return  void
446  */
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__ );
452     }
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__ );
460         }
461         return;
462     }
463
464     //load parameter value
465     load_parameter( err );
466     if( 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__ );
472         }
473         return;
474     }
475
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" );
481         return;
482     }
483
484     logger_implement_access *access_log_instance = NULL;
485     // access log instance create.
486     if( element.access_log_file_name != "" ) {
487         access_log_instance 
488                         = logger_access_manager::getInstance().find_logger_implement_access( 
489                                                                     element.access_log_file_name, 
490                                                                     element.access_log_rotate_arguments, 
491                                                                     err );
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" );
497             return;
498         }
499     }
500
501     //get cpumask
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 );
506 #endif
507
508     //bind acceptor
509     boost::system::error_code    acceptor_err;
510     acceptor_.open( element.tcp_accept_endpoint.protocol(), acceptor_err );
511     if( acceptor_err ){
512         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 5, acceptor_err.message(), __FILE__, __LINE__ );
513         err.setter( true, acceptor_err.message() );
514         return;
515     }
516     acceptor_.set_option( boost::asio::ip::tcp::acceptor::reuse_address( true ), acceptor_err );
517     if( acceptor_err ){
518         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 6, acceptor_err.message(), __FILE__, __LINE__ );
519         err.setter( true, acceptor_err.message() );
520         return;
521     }
522     if( likely(address.is_v6()) ) {
523         boost::asio::ip::v6_only option(true);
524         acceptor_.set_option( option, acceptor_err );
525         if( acceptor_err ) {
526             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 7, acceptor_err.message(), __FILE__, __LINE__ );
527             err.setter( true, acceptor_err.message() );
528             return;
529         }
530     }
531     acceptor_.bind( element.tcp_accept_endpoint, acceptor_err );
532     if( acceptor_err ){
533         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 8, acceptor_err.message(), __FILE__, __LINE__ );
534         err.setter( true, acceptor_err.message() );
535         return;
536     }
537
538     //read replication data
539     read_replicationdata();
540
541     //load protocol module
542     protomod = protocol_module_control::getInstance().load_module( element.protocol_module_name );
543     if( NULL == protomod ){
544         //ERROR case
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__ );
552         }
553         return;
554     }
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 );
577
578     protocol_module_base::check_message_result pm_result;
579     
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__ );
588         }
589         return;
590     }
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__ );
599         }
600         return;
601     }
602
603     protomod->get_option_info(protocol_module_for_indication_options);
604     element.protocol_module_for_indication_options = protocol_module_for_indication_options;
605
606     //load schedule module    
607     schedmod = schedule_module_control::getInstance().load_module( element.schedule_module_name );
608     if( NULL == schedmod ){
609         //ERROR case
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__ );
617         }
618         return;
619     }
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 );
635
636     // access log flag set 
637     access_log_flag = false;
638     if ( element.access_log_flag == 1 ) {
639         access_log_flag = true;
640     }
641
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(); 
646     } else {
647         element.access_log_rotate_verbose_info = element.access_log_rotate_key_info;
648     }
649     access_log_file_name = element.access_log_file_name;
650     access_log_rotate_arguments = element.access_log_rotate_arguments;
651
652     // SSL setting
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;
657         // get SSL parameter
658         if(unlikely(!get_ssl_parameter())) {
659             //Error
660             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 11, "get ssl parameter failed", __FILE__, __LINE__ );
661             err.setter( true, "get ssl parameter failed" );
662             return;
663         }
664         // set SSL configuration
665         if(unlikely(!set_ssl_config())) {
666             //Error
667             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 12, "set ssl config failed", __FILE__, __LINE__ );
668             err.setter( true, "set ssl config failed" );
669             return;
670         }
671         ssl_virtualservice_mode_flag = true;
672     }
673
674
675     set_socket_option();
676
677     //create session pool
678     {
679         for( int i = 0; i < param_data.session_pool_size; ++i ){
680             try{
681                 tcp_session*    sess    = new tcp_session(*this,
682                                       dispatcher,
683                                       set_sock_opt,
684                                       element.tcp_accept_endpoint,
685                                       ssl_virtualservice_mode_flag,
686                                       sslcontext,
687                                       is_session_cache_use,
688                                       handshake_timeout,
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__ );
698                     }
699                     return;
700                 }
701                 session_thread_control*    p_stc = new session_thread_control( sess, vsnic_cpumask, rsnic_cpumask, -1 );
702                 while( !pool_sessions.push( p_stc ) ){}
703             }
704             catch( std::bad_alloc ex ){
705                 Logger::putLogFatal( 
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__ );
712                 }
713                 return;
714             }
715         }
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__ );
723         }
724     }
725
726     err.setter( false, "" );
727
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__ );
733     }
734 }
735
736 /*!
737  * finalize virtualservice(TCP)
738  *
739  * @param   erro_code
740  * @return  void
741  */
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__ );
747
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__ );
754     }
755
756     //stop main loop
757     stop();
758
759     while(active_sessions.size()){
760         boost::this_thread::yield();
761     }
762
763     for(;;){
764         tcp_session*                tmp_session    = NULL;
765         session_thread_control*        tmp_stc        = NULL;
766         waiting_sessions.pop( tmp_session, tmp_stc );
767         if( !tmp_stc ){
768             break;
769         }
770         for(;;){
771             if( likely( pool_sessions.push( tmp_stc ) ) )break;
772         }
773     }
774
775     //release sessions[i]->join();
776     while( !pool_sessions.empty() ){
777         session_thread_control*    stc = pool_sessions.pop();
778         stc->join();
779         {
780             boost::mutex::scoped_lock upthread_wait( stc->get_upthread_mutex() );
781             boost::mutex::scoped_lock downthread_wait( stc->get_downthread_mutex() );
782         }
783         delete    stc;
784         stc = NULL;
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__ );
789         }
790     }
791
792     //unload ProtocolModule
793     if( protomod ){
794         //finalize ProtocolModule
795         protomod->finalize();
796         //unload ProtocolModule
797         protocol_module_control::getInstance().unload_module( protomod );
798         protomod = NULL;
799     }
800     //unload ScheduleModule
801     if( schedmod ){
802         schedule_module_control::getInstance().unload_module( schedmod );
803         schedmod = NULL;
804     }
805
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__ );
814     }
815
816     //clear replication_data
817     bool    replication_status    = true;
818     replication&    rep_noconst = const_cast<replication&>( rep );
819
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;
827         }
828     
829         //check maxdatasize
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;
835         }
836         if( (NULL != rep_header_ptr) && (replication_status) ){
837             //lock replication area
838             rep_noconst.lock( REP_AREA_NAME );
839             //set data_num = 0
840             rep_header_ptr->data_num = 0;
841             //unlock replication area
842             rep_noconst.unlock( REP_AREA_NAME );
843         }
844     }
845
846     vsd.release_virtual_service( element );
847
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,
855                                    fmt.str(),
856                                    __FILE__, __LINE__ );
857         }
858     }
859     
860     err.setter( false, "" );
861
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__ );
867     }
868
869 }
870
871 /*!
872  * equal compare virtualservice(TCP)
873  *
874  * @param   virtualservice_base
875  * @return  bool ( true = equal )
876  */
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__ );
881
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 ) );
885 }
886
887 /*!
888  * not-equal compare virtualservice(TCP)
889  *
890  * @param   virtualservice_base
891  * @return  bool ( true = not-equal )
892  */
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__ );
898     }
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 ) );
902 }
903
904 /*!
905  * add VirtualService( not-imprement )
906  *
907  * @param   virtualservice_element
908  * @param   err
909  * @return  void
910  */
911 void    l7vs::virtualservice_tcp::set_virtualservice( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
912     err.setter( false, "" );
913 }
914
915 /*!
916  * edit VirtualService
917  *
918  * @param   virtualservice_element
919  * @param   err
920  * @return  void
921  */
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__ );
928     }
929
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__ );
943         }
944         return;
945     }
946
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 ){
952             //ERROR case
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__ );
961             }
962             return;
963         }
964         element.schedule_module_name = elem.schedule_module_name;
965     }
966 /*
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 );
971         if( result.flag ){
972             for( size_t i = 0; i < elem.protocol_args.size(); ++i ){
973                 element.protocol_args.push_back( elem.protocol_args[i] );
974             }
975         }else{
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__ );
983             }
984             return;
985         }
986     }else{
987         //ERROR case
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__ );
996         }
997         return;
998     }
999 */
1000     //update values
1001     //qos_upstream;
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;
1006     //qos_downstream;
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;
1016     //sorry_flag;
1017     if( INT_MAX == elem.sorry_flag )
1018         element.sorry_flag            = 0;
1019     else if( 0 != elem.sorry_flag )
1020         element.sorry_flag            = 1;
1021     //sorry_endpoint;
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 ) );
1030     }else{
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;
1034
1035         active_sessions.do_all( boost::bind( &session_thread_control::session_sorry_mode_change, _1, elem.sorry_flag ) );
1036     }
1037
1038     // access log flag ON and access log filename not set.
1039     if ( elem.access_log_flag == 1 && element.access_log_file_name == "" ) {
1040         //ERROR case
1041         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 15, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
1042         err.setter( true, "access log flag change err." );
1043         return;
1044     }
1045
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;
1054     }
1055
1056     err.setter( false, "" );
1057
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__ );
1064     }
1065 }
1066
1067 /*!
1068  * add realserver
1069  *
1070  * @param   virtualservice_element
1071  * @param   err
1072  * @return  void
1073  */
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__ );
1080     }
1081
1082     virtualservice_element&    in_element = const_cast<virtualservice_element&>( in );
1083
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__ );
1093         }
1094         return;
1095     }    
1096     //check rs num
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__ );
1105         }
1106         return;
1107     }
1108     //lock rs_list_ref_count_inc_mutex
1109     rw_scoped_lock    inc_lock( rs_list_ref_count_inc_mutex );
1110
1111     //waiting, rs_list_ref_count become 0
1112     boost::xtime        interval;
1113     boost::mutex        mtx;
1114     boost::condition    cond;
1115
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 );
1120     }
1121
1122     //check duplication realserver
1123     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1124          itr != in_element.realserver_vector.end();
1125          ++itr ){
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__ );
1136                 }
1137                 return;
1138             }
1139         }
1140     }
1141
1142     //pause active sessions
1143     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1144
1145     //add realserver
1146     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1147          itr != in_element.realserver_vector.end();
1148          ++itr ){
1149         realserver    rs;
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 );
1154     }
1155
1156     //run active sessions
1157     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1158
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__ );
1165     }
1166 }
1167
1168 /*!
1169  * edit realserver
1170  *
1171  * @param   virtualservice_element
1172  * @param   err
1173  * @return  void
1174  */
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__ );
1181     }
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__ );
1191         }
1192         return;
1193     }    
1194
1195     //lock rs_list_ref_count_inc_mutex
1196     rw_scoped_lock    inc_lock( rs_list_ref_count_inc_mutex );
1197
1198     //waiting, rs_list_ref_count become 0
1199     boost::xtime        interval;
1200     boost::mutex        mtx;
1201     boost::condition    cond;
1202
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 );
1207     }
1208
1209     virtualservice_element&    in_element = const_cast<virtualservice_element&>( in );
1210
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();
1214          ++itr ){
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 ){
1219                 exist_flag = true;
1220             }
1221         }
1222         if( !exist_flag ){
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__ );
1230             }
1231             return;
1232         }
1233     }
1234
1235     //pause active sessions
1236     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1237
1238     //edit realserver
1239     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1240          itr != in_element.realserver_vector.end();
1241          ++itr ){
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;
1246
1247                 if( itr->weight != -1 ) {
1248                     rs_itr->weight            = itr->weight;
1249                 }
1250
1251             }
1252         }
1253     }
1254
1255     //run active sessions
1256     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1257
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__ );
1265     }
1266 }
1267
1268 /*!
1269  * delete realserver
1270  *
1271  * @param   virtualservice_element
1272  * @param   err
1273  * @return  void
1274  */
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__ );
1281     }
1282
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__ );
1292         }
1293         return;
1294     }    
1295
1296     //lock rs_list_ref_count_inc_mutex
1297     rw_scoped_lock    inc_lock( rs_list_ref_count_inc_mutex );
1298
1299     //waiting, rs_list_ref_count become 0
1300     boost::xtime        interval;
1301     boost::mutex        mtx;
1302     boost::condition    cond;
1303
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 );
1308     }
1309
1310     virtualservice_element&    in_element = const_cast<virtualservice_element&>( in );
1311
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();
1315          ++itr ){
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 ){
1320                 exist_flag = true;
1321             }
1322         }
1323         if( !exist_flag ){
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__ );
1331             }
1332             return;
1333         }
1334     }
1335
1336     //pause active sessions
1337     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1338
1339     //del realserver
1340     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1341          itr != in_element.realserver_vector.end();
1342          ++itr ){
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 );
1347                 break;
1348             }
1349         }
1350     }
1351
1352     //run active sessions
1353     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1354
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__ );
1361     }
1362 }
1363
1364 /*!
1365  * main loop of virtualservice(TCP)
1366  *
1367  * @param   void
1368  * @return  void
1369  */
1370 void    l7vs::virtualservice_tcp::run(){
1371     Logger    funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function : void virtualservice_tcp::run()", __FILE__, __LINE__ );
1372
1373     if( pool_sessions.size() == 0 ){
1374         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.", __FILE__, __LINE__ );
1375         return;
1376     }
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);
1384         if(unlikely(ec)){
1385             //ERROR
1386             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 17, "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__ );
1387         }
1388     }
1389     //start listen
1390     acceptor_.listen();
1391
1392     //switch active a session
1393     session_thread_control*    stc_ptr;
1394     {
1395         stc_ptr = pool_sessions.pop();
1396         if( !stc_ptr ){
1397             return;
1398         }
1399         //regist accept event handler
1400         waiting_sessions.insert( stc_ptr->get_session().get(), stc_ptr );
1401     }
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 ) );
1405     } else {
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 ) );
1408     }
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 ) );
1413
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 ) );
1426
1427     //run dispatcher(start io_service loop)
1428     dispatcher.run();
1429
1430     //stop all active sessions
1431     {
1432         active_sessions.do_all( boost::bind( &session_thread_control::session_stop, _1 ) );
1433     }
1434 }
1435
1436 /*!
1437  * stop loop
1438  *
1439  * @param   void
1440  * @return  void
1441  */
1442 void    l7vs::virtualservice_tcp::stop(){
1443     Logger    funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function : void virtualservice_tcp::stop()", __FILE__, __LINE__ );
1444
1445     boost::system::error_code    err;
1446
1447     acceptor_.close( err );
1448     if( err ){
1449         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__ );
1450     }
1451
1452     //stop dispatcher
1453     dispatcher.stop();
1454 }
1455
1456 /*!
1457  * increment active-connection count
1458  *
1459  * @param   endpoint
1460  * @return  void
1461  */
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");
1466         formatter % in;
1467         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__ );
1468     }
1469     rs_list_lock();
1470     for( std::list<realserver>::iterator itr = rs_list.begin();
1471          itr != rs_list.end();
1472          ++itr ){
1473         if( itr->tcp_endpoint == in ){
1474             itr->increment_active();
1475             break;
1476         }
1477     }
1478     rs_list_unlock();
1479     active_count++;
1480
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__ );
1483     }
1484 }
1485
1486 /*!
1487  * increment in-active-connection (and decrement active-connection count)
1488  *
1489  * @param   endpoint
1490  * @return  void
1491  */
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");
1496         formatter % in;
1497         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__ );
1498     }
1499     rs_list_lock();
1500     for( std::list<realserver>::iterator itr = rs_list.begin();
1501          itr != rs_list.end();
1502          ++itr ){
1503         if( itr->tcp_endpoint == in ){
1504             itr->decrement_active();
1505             itr->increment_inact();
1506             break;
1507         }
1508     }
1509     rs_list_unlock();
1510     active_count--;
1511
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__ );
1514     }
1515 }
1516
1517 /*!
1518  * release_session
1519  *
1520  * @param   void
1521  * @return  void
1522  */
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__ );
1529     }
1530
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 )");
1535             fmt % session_ptr;
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__ );
1538         }
1539         return;
1540     }
1541
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__ );
1552     }
1553     active_sessions.erase( session_ptr );
1554     stc_ptr->get_session()->initialize();
1555     for(;;){
1556         if( likely( pool_sessions.push( stc_ptr ) ) ){
1557             break;
1558         }
1559     }
1560
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__ );
1571
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__ );
1576     }
1577 }
1578
1579 //!
1580 // set_socket_option
1581 // @return  void
1582 void l7vs::virtualservice_tcp::set_socket_option(){
1583
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__ );
1587     }
1588  
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;
1594         
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;
1607
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;
1613         }
1614     }
1615
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;
1620         }
1621     }
1622
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;
1627         }
1628     }
1629
1630     if ( element.socket_option_tcp_quickack != 0  ) {
1631         
1632         set_sock_opt.quickack_opt = true;
1633         if ( element.socket_option_tcp_quickack == 1  ) {
1634             set_sock_opt.quickack_val = true;
1635         }
1636     }
1637
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__ );
1650     }
1651     //----Debug log----------------------------------------------------------------------
1652
1653 }
1654
1655 //!
1656 //! get private key file password (for callback function)
1657 //! @return password string
1658 std::string l7vs::virtualservice_tcp::get_ssl_password()
1659 {
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__ );
1668     }
1669     //*------ DEBUG LOG END ------*/
1670
1671     // Get password from file.
1672     std::string retstr = "";
1673     FILE *fp;
1674     char buf[MAX_SSL_PASSWD_SIZE + 3];
1675     if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1676                     "r")) == NULL) {
1677         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1678                              "Password file cannot open.", __FILE__, __LINE__ );
1679     } else {
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__ );
1684         } else {
1685             if ( strlen(buf) > MAX_SSL_PASSWD_SIZE ) {
1686                 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1687                                      "Password is too long.",
1688                                      __FILE__, __LINE__ );
1689             } else {
1690                 buf[strlen(buf) - 1] = '\0';
1691                 retstr = buf;
1692             }
1693         }
1694         fclose(fp);
1695     }
1696
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__ );
1706     }
1707     //*------ DEBUG LOG END ------*/
1708
1709     return retstr;
1710 }
1711
1712 //!
1713 //! Convert verify option string to intger(#define).
1714 //!
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)
1719 {
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__ );
1730     }
1731     //*------ DEBUG LOG END ------*/
1732
1733     int ret = -1;
1734     //!
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
1740     //
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;
1749     } else {
1750         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
1751                              "verify option string no match.",
1752                              __FILE__, __LINE__ );
1753     }
1754
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__ );
1765     }
1766     //*------ DEBUG LOG END ------*/
1767     // if ret == -1 then No match.
1768     return ret;
1769 }
1770
1771 //!
1772 // Convert SSL option string to intger(#define).
1773 //
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)
1778 {
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__ );
1789     }
1790     //*------ DEBUG LOG END ------*/
1791
1792     long int ret = -1;
1793     //!
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
1843         ret = SSL_OP_ALL;
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;
1878     } else {
1879         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
1880                              "ssl option string no match.",
1881                              __FILE__, __LINE__ );
1882     }
1883
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__ );
1894     }
1895     //------ DEBUG LOG END ------*/
1896     // if ret == -1 then No match.
1897     return ret;
1898 }
1899
1900 //!
1901 //! get ssl parameter
1902 //! @return get ssl parameter result
1903 bool l7vs::virtualservice_tcp::get_ssl_parameter()
1904 {
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__ );
1910     }
1911     //*------ DEBUG LOG END ------*/
1912     typedef std::vector< std::string > string_vector_type;
1913
1914     Parameter param;
1915     string_vector_type string_vector;
1916     l7vs::error_code err;
1917     bool retbool = false;
1918
1919     try {
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__ );
1925             throw -1;
1926         }
1927
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;
1937         }
1938
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__ );
1946             throw -1;
1947         }
1948
1949         // Get parameter "cert_chain_dir".
1950         cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
1951                                           "cert_chain_dir",
1952                                           err,
1953                                           ssl_file_name);
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;
1959         }
1960
1961         // Get parameter "cert_chain_file".
1962         cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
1963                                            "cert_chain_file",
1964                                            err,
1965                                            ssl_file_name);
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__ );
1970             throw -1;
1971         }
1972
1973         // Get parameter "private_key_dir".
1974         private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
1975                                            "private_key_dir",
1976                                            err,
1977                                            ssl_file_name);
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;
1983         }
1984
1985         // Get parameter "private_key_file".
1986         private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
1987                                             "private_key_file",
1988                                             err,
1989                                             ssl_file_name);
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__ );
1994             throw -1;
1995         }
1996
1997         // Get parameter "private_key_filetype".
1998         // and convert string to filetype define value.
1999         //!
2000         // /usr/include/openssl/ssl.h
2001         // #define SSL_FILETYPE_PEM        X509_FILETYPE_PEM  ->1
2002         // #define SSL_FILETYPE_ASN1       X509_FILETYPE_ASN1 ->2
2003         //
2004
2005         std::string filetype_str = param.get_string(
2006                                        l7vs::PARAM_COMP_SSL,
2007                                        "private_key_filetype",
2008                                        err,
2009                                        ssl_file_name);
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;
2019         } else {
2020             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
2021                         "private_key_filetype convert error.",
2022                         __FILE__, __LINE__ );
2023             throw -1;
2024         }
2025
2026         // Get parameter "private_key_passwd_dir".
2027         private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2028                                                   "private_key_passwd_dir",
2029                                                   err,
2030                                                   ssl_file_name);
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;
2036         }
2037
2038         // Get parameter "private_key_passwd_file".
2039         private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2040                                                    "private_key_passwd_file",
2041                                                    err,
2042                                                    ssl_file_name);
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__ );
2047             throw -1;
2048         }
2049
2050         // Get parameter "verify_options".
2051         param.get_multistring(l7vs::PARAM_COMP_SSL,
2052                               "verify_options",
2053                               string_vector,
2054                               err,
2055                               ssl_file_name);
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;
2061         } else {
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__ );
2071                     throw -1;
2072                 }
2073                 verify_options = (verify_options | int_val);
2074             }
2075         }
2076
2077         // Get parameter "verify_cert_depth".
2078         verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2079                                           "verify_cert_depth",
2080                                           err,
2081                                           ssl_file_name);
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__ );
2092             throw -1;
2093         }
2094
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,
2099                               "ssl_options",
2100                               string_vector,
2101                               err,
2102                               ssl_file_name);
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;
2109         } else {
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__ );
2119                     throw -1;
2120                 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2121                     is_tmp_dh_use = true;
2122                 }
2123                 ssl_options = (ssl_options | longint_val);
2124             }
2125         }
2126
2127         if (is_tmp_dh_use) {
2128             // Get parameter "tmp_dh_dir".
2129             tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2130                                           "tmp_dh_dir",
2131                                           err,
2132                                           ssl_file_name);
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;
2138             }
2139             // Get parameter "tmp_dh_file".
2140             tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2141                                            "tmp_dh_file",
2142                                            err,
2143                                            ssl_file_name);
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__ );
2148                 throw -1;
2149             }
2150         }
2151
2152         // Get parameter "cipher_list".
2153         cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2154                                        "cipher_list",
2155                                        err,
2156                                        ssl_file_name);
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;
2162         }
2163
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,
2168                                                  "session_cache",
2169                                                  err,
2170                                                  ssl_file_name);
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;
2180         } else {
2181             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2182                         "Invalid session_cache parameter value.",
2183                         __FILE__, __LINE__ );
2184             throw -1;
2185         }
2186
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",
2192                                                err,
2193                                                ssl_file_name);
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__ );
2204                 throw -1;
2205             }
2206             // Get parameter "session_cache_timeout".
2207             session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2208                                                   "session_cache_timeout",
2209                                                   err,
2210                                                   ssl_file_name);
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__ );
2221                 throw -1;
2222             }
2223         } else {
2224             session_cache_mode = SSL_SESS_CACHE_OFF;
2225         }
2226
2227         //// SSL handshake timer parameter
2228         // Get parameter "timeout_sec".
2229         handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2230                                           "timeout_sec",
2231                                           err,
2232                                           ssl_file_name);
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__ );
2242             throw -1;
2243         }
2244
2245         retbool = true;
2246
2247     } catch (int e) {
2248         retbool = false;
2249     }
2250
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             << ", ";
2271         }
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 << ", ";
2277         }
2278         buf<<"handshake_timeout = "      << handshake_timeout;
2279         Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2280                             buf.str(),
2281                             __FILE__, __LINE__ );
2282     }
2283     //*------ DEBUG LOG END ------*/
2284     return retbool;
2285 }
2286
2287 //!
2288 // set ssl context and ssl session cache configuration
2289 // @return set ssl config result
2290 bool l7vs::virtualservice_tcp::set_ssl_config()
2291 {
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__ );
2298     }
2299     //*------ DEBUG LOG END ------*/
2300
2301     bool retbool = false;
2302
2303     try {
2304         //// SSL context setting.
2305         // Set root CA.
2306         if (ca_file.size() == 0) {
2307             // specified CA path.
2308             try {
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,
2314                             buf.str(),
2315                             __FILE__, __LINE__ );
2316                 throw -1;
2317             }
2318         } else {
2319             // specified CA file.
2320             try {
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,
2326                             buf.str(),
2327                             __FILE__, __LINE__ );
2328                 throw -1;
2329             }
2330         }
2331
2332         // Set certificate chain file.
2333         try {
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__ );
2341             throw -1;
2342         }
2343
2344         // Set password callback function.
2345         try {
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__ );
2353             throw -1;
2354         }
2355
2356         // Set private key file and filetype.
2357         try {
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__ );
2365             throw -1;
2366         }
2367
2368         // Set verify options on the context.
2369         try {
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__ );
2376             throw -1;
2377         }
2378
2379         // Set verify depth on the context.
2380         SSL_CTX_set_verify_depth(sslcontext.impl(), verify_cert_depth);
2381
2382         // Set SSL options on the context.
2383         try {
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__ );
2390             throw -1;
2391         }
2392
2393         // Set temporary Diffie-Hellman parameters file.
2394         if (is_tmp_dh_use) {
2395             try {
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,
2401                             buf.str(),
2402                             __FILE__, __LINE__ );
2403                 throw -1;
2404             }
2405
2406         }
2407
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,
2414                         buf.str(),
2415                         __FILE__, __LINE__ );
2416             throw -1;
2417         }
2418
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(
2423                               sslcontext.impl(),
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,
2428                             buf.str(),
2429                             __FILE__, __LINE__ );
2430                 throw -1;
2431             }
2432
2433             // Set session cache mode on the context.
2434             SSL_CTX_set_session_cache_mode(
2435                                         sslcontext.impl(),session_cache_mode);
2436
2437             // Set session cache size on the context.
2438             SSL_CTX_sess_set_cache_size(sslcontext.impl(), session_cache_size);
2439
2440             // Set session cache timeout on the context.
2441             SSL_CTX_set_timeout(sslcontext.impl(), session_cache_timeout);
2442
2443         } else {
2444             // session cache OFF.
2445             SSL_CTX_set_session_cache_mode(sslcontext.impl(),
2446                                            SSL_SESS_CACHE_OFF);
2447         }
2448
2449         retbool = true;
2450
2451     } catch (int e) {
2452         retbool = false;
2453     }
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__ );
2462     }
2463     //*------ DEBUG LOG END ------*/
2464     return retbool;
2465 }
2466
2467 //!
2468 // flush ssl session
2469 void l7vs::virtualservice_tcp::flush_ssl_session()
2470 {
2471     // check expired cached sessions and do flushing
2472     // Need ssl_context lock?
2473     SSL_CTX_flush_sessions(sslcontext.impl(), time(0));
2474 }
2475
2476 //!
2477 // get ssl configuration form ssl context. (for debug)
2478 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream& buf)
2479 {
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());
2485     buf<<"] ";
2486     buf<<"Cache size["<<SSL_CTX_sess_get_cache_size(sslcontext.impl())<< "] ";
2487     buf<<"Cache timeout[" << SSL_CTX_get_timeout(sslcontext.impl()) << "] ";
2488 }
2489
2490 //!
2491 // get ssl session cache information form ssl context. (for debug)
2492 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream& buf)
2493 {
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())  << "] ";
2503 }
2504