OSDN Git Service

ticket #395
[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 /*!
57  * virtualservice_tcp class destructor.
58  */
59 l7vs::virtualservice_tcp::~virtualservice_tcp(){
60 }
61
62 /*!
63  * replication interrupt event
64  *
65  * @param   err
66  * @return  void
67  */
68 void    l7vs::virtualservice_tcp::handle_replication_interrupt( const boost::system::error_code& err ){
69     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
70         boost::format    fmt("in_function : void virtualservice_tcp::handle_replication_interrupt( "
71                             "const boost::system::error_code& err ) : err = %s, err.message = %s");
72         fmt % ( err ? "true" : "false") % err.message();
73         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 20, fmt.str(), __FILE__, __LINE__ );
74     }
75
76     if( unlikely( err ) ){
77         //ERROR case
78         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, err.message(), __FILE__, __LINE__ );
79         return;
80     }
81
82     bool    newdata    = true;
83     replication&    rep_noconst = const_cast<replication&>( rep );
84
85     if( replication::REPLICATION_SINGLE == rep_noconst.get_status() ){
86         Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "replication mode is single.", __FILE__, __LINE__ );
87         return;
88     }
89
90     std::stringstream    tmp_tcp_ep;
91     tmp_tcp_ep        << element.tcp_accept_endpoint;
92     std::stringstream    tmp_udp_ep;
93     tmp_udp_ep        << element.udp_recv_endpoint;
94     std::stringstream    tmp_sorry_ep;
95     tmp_sorry_ep    << element.sorry_endpoint;
96     
97     //get replication area
98     unsigned int    rep_size = 0;
99     replication_header*    rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
100     if( (rep_header_ptr == NULL) || (0 == rep_size) ){
101         Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 1, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
102         return;
103     }
104
105     //check maxdatasize
106     if( ( rep_size * DATA_SIZE ) <
107         ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
108         Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
109         return;
110     }
111
112     //lock replication area
113     rep_noconst.lock( REP_AREA_NAME );
114
115     //read header value and set loop count
116     unsigned int loop_cnt = rep_header_ptr->data_num;
117     //if data_num over MAX_REPLICATION_DATA_NUM, data_num = 0
118     if( static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt )
119         loop_cnt = 0;
120
121     //set start pointer(pointer of replication_data)
122     replication_data*    rep_data_ptr = reinterpret_cast<replication_data*>( ++rep_header_ptr );
123
124     //find vs(loop)
125     for( unsigned int i = 0; i < loop_cnt; ++i ){
126         //check equal udpmode and tcp_accept_endpoint
127         if( (rep_data_ptr->udpmode == element.udpmode )&&
128             ( 0 == strncmp( rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 47 ) ) ){
129             newdata = false;
130             break;
131         }
132         //increment data pointer
133         ++rep_data_ptr;
134     }
135
136     //if it is new data, increment data num.
137     if( newdata ){
138         rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
139         ++(rep_header_ptr->data_num);
140     }
141     //write replication data
142     rep_data_ptr->udpmode        = element.udpmode;
143     strncpy( rep_data_ptr->tcp_endpoint, tmp_tcp_ep.str().c_str(), 48 );
144     strncpy( rep_data_ptr->udp_endpoint, tmp_udp_ep.str().c_str(), 48 );
145     rep_data_ptr->sorry_maxconnection    = element.sorry_maxconnection;
146     strncpy( rep_data_ptr->sorry_endpoint, tmp_sorry_ep.str().c_str(), 48 );
147     rep_data_ptr->sorry_flag    = element.sorry_flag;
148     rep_data_ptr->qos_up        = element.qos_upstream;
149     rep_data_ptr->qos_down        = element.qos_downstream;
150
151     //unlock replication area
152     rep_noconst.unlock( REP_AREA_NAME );
153
154     //register handle_replication_interrupt
155     replication_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
156     replication_timer->async_wait( boost::bind( &virtualservice_tcp::handle_replication_interrupt, 
157                                             this, boost::asio::placeholders::error ) );
158
159     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
160         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 21, "out_function : void virtualservice_tcp::handle_replication_interrupt( const boost::system::error_code& err )", __FILE__, __LINE__ );
161     }
162 }
163
164 /*!
165  * read replication data
166  *
167  * @param   read_replicationdata
168  * @param    error_code
169  * @return  void
170  */
171 void    l7vs::virtualservice_tcp::read_replicationdata(){
172     Logger    funclog( LOG_CAT_L7VSD_VIRTUALSERVICE, 22, "function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
173
174     replication&    rep_noconst = const_cast<replication&>( rep );
175
176     if( replication::REPLICATION_SINGLE == rep_noconst.get_status() ){
177         Logger::putLogInfo( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, "replication mode is single.", __FILE__, __LINE__ );
178         return;
179     }
180
181     unsigned int    rep_size = 0;
182     replication_header*    rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
183     if( (rep_header_ptr == NULL) || (0 == rep_size) ){
184         Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 3, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
185         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
186             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 23, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
187         }
188         return;
189     }
190
191     //check maxdatasize
192     if( ( rep_size * DATA_SIZE ) <
193         ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
194         Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 4, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
195         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
196             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 24, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
197         }
198         return;
199     }
200     //lock replication area
201     rep_noconst.lock( REP_AREA_NAME );
202
203     //read header value and set loop count
204     unsigned int loop_cnt = rep_header_ptr->data_num;
205     //if data_num over MAX_REPLICATION_DATA_NUM, set data_num = 0
206     if( static_cast<unsigned int>(MAX_REPLICATION_DATA_NUM) < loop_cnt ){
207         Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 5, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
208         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
209             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 25, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
210         }
211         rep_header_ptr->data_num = 0;
212         rep_noconst.unlock( REP_AREA_NAME );
213         return;
214     }
215
216     //set start pointer(pointer of replication_data)
217     replication_data*    rep_data_ptr = reinterpret_cast<replication_data*>( ++rep_header_ptr );
218
219     //find vs(loop)
220     for( unsigned int i = 0; i < loop_cnt; ++i ){
221         //get tcp endpointdata
222         std::string        tmpstr = rep_data_ptr->tcp_endpoint;
223         std::string        ipaddr;
224         unsigned short    portno;
225         try{
226             portno    = boost::lexical_cast<unsigned short>( tmpstr.substr( (tmpstr.rfind( ":" )+1) ) );
227         }
228         catch( const boost::bad_lexical_cast& err ){
229             portno    = 0;
230         }
231         if( tmpstr[0] == '[' ){
232             //IPv6 endpoint
233             ipaddr    = tmpstr.substr( 1, (tmpstr.rfind( "]" )-1) );
234         }else{
235             //IPv4 endpoint
236             ipaddr    = tmpstr.substr( 0, tmpstr.rfind( ":" ) );
237         }
238         //check equal udpmode and tcp_accept_endpoint
239         if( (rep_data_ptr->udpmode == element.udpmode )&&
240             ( tcp_endpoint_type( boost::asio::ip::address::from_string( ipaddr ), portno ) == element.tcp_accept_endpoint ) ){
241                 element.sorry_maxconnection    = rep_data_ptr->sorry_maxconnection;
242             tmpstr    = rep_data_ptr->sorry_endpoint;
243             try{
244                 portno    = boost::lexical_cast<unsigned short>( tmpstr.substr( (tmpstr.rfind( ":" )+1) ) );
245             }
246             catch( const boost::bad_lexical_cast& err ){
247                 portno    = 0;
248             }
249             if( tmpstr[0] == '[' ){
250                 //IPv6 endpoint
251                 ipaddr    = tmpstr.substr( 1, (tmpstr.rfind( "]" )-1) );
252             }else{
253                 //IPv4 endpoint
254                 ipaddr    = tmpstr.substr( 0, tmpstr.rfind( ":" ) );
255             }
256             element.sorry_endpoint        = 
257                     tcp_endpoint_type( boost::asio::ip::address::from_string( ipaddr ), portno );
258             element.sorry_flag            = rep_data_ptr->sorry_flag;
259             element.qos_upstream        = rep_data_ptr->qos_up;
260             element.qos_downstream        = rep_data_ptr->qos_down;
261             break;
262         }
263         //increment data pointer
264         ++rep_data_ptr;
265     }
266
267     //unlock replication area
268     rep_noconst.unlock( REP_AREA_NAME );
269
270     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
271         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 26, "out_function : void virtualservice_tcp::read_replicationdata()", __FILE__, __LINE__ );
272     }
273 }
274
275 /*!
276  * accept event
277  *
278  * @param   handle_accept
279  * @param    error_code
280  * @return  void
281  */
282 void    l7vs::virtualservice_tcp::handle_accept( const l7vs::session_thread_control* stc_ptr, const boost::system::error_code& err ){
283     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
284         boost::format funclog_fmt("in_function : void virtualservice_tcp::handle_accept( "
285                                 "const boost::shared_ptr<session_thread_control> , "
286                                 "const boost::system::error_code& err ) : err = %s, err.message = %s");
287         funclog_fmt % ( err ? "true" : "false") % err.message();
288         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 27, funclog_fmt.str(), __FILE__, __LINE__ );
289     }
290
291     session_thread_control*        stc_ptr_noconst = const_cast<session_thread_control*>( stc_ptr );
292
293     if( unlikely( err ) ){
294         //ERROR case
295         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 2, err.message(), __FILE__, __LINE__ );
296         return;
297     }
298
299     tcp_session*    tmp_session    = stc_ptr_noconst->get_session().get();
300
301     // ssl session cache flush
302     if( ( ssl_file_name != "" ) && ( is_session_cache_use == true ) ) {
303
304         //*-------- DEBUG LOG --------*/
305         if (unlikely(LOG_LV_DEBUG ==
306                      Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
307             std::stringstream buf;
308             buf << "virtualservice_tcp::handle_accept() : ";
309             buf << "ssl session cache flush before : ";
310             get_ssl_session_cache_info(buf);
311             Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
312                         buf.str(),
313                         __FILE__, __LINE__ );
314         }
315         //*------ DEBUG LOG END ------*/
316
317         long ssl_cache_num = SSL_CTX_sess_number(sslcontext.impl());
318         if ( ssl_cache_num >= session_cache_size ) {
319             flush_ssl_session();
320         }
321
322         //*-------- DEBUG LOG --------*/
323         if (unlikely(LOG_LV_DEBUG ==
324                      Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
325             std::stringstream buf;
326             buf << "virtualservice_tcp::handle_accept() : ";
327             buf << "ssl session cache flush after : ";
328             get_ssl_session_cache_info(buf);
329             Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
330                         buf.str(),
331                         __FILE__, __LINE__ );
332         }
333         //*------ DEBUG LOG END ------*/
334
335     }
336
337     // send access log output ON or OFF message to tcp_session
338     stc_ptr_noconst->session_access_log_output_mode_change( access_log_flag );
339
340     active_sessions.insert( tmp_session, stc_ptr_noconst );
341
342     //check sorry flag and status
343     if ( unlikely( ( 0 != element.sorry_flag ) ||
344                    ( ( 0 < element.sorry_maxconnection ) &&
345                      ( ( active_count.get() >= static_cast<size_t>( element.sorry_maxconnection ) ) ) ) ) ){
346         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
347             boost::format   fmt( "Connection switch Sorry mode. : active_session.size = %d / active_count.get = %d" );
348             fmt % active_sessions.size() % active_count.get();
349             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 30, fmt.str(), __FILE__, __LINE__ );
350         }
351         stc_ptr_noconst->get_session()->set_virtual_service_message( tcp_session::SORRY_STATE_ENABLE );
352     }
353
354     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
355         boost::format    fmt1( "active session thread id = %d" );
356         fmt1 % stc_ptr_noconst->get_upthread_id();
357         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 31, fmt1.str(), __FILE__, __LINE__ );
358         boost::format    fmt2( "pool_session.size   = %d" );
359         fmt2 % pool_sessions.size();
360         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 32, fmt2.str(), __FILE__, __LINE__ );
361         boost::format    fmt3( "active_session.size = %d" );
362         fmt3 % active_sessions.size();
363         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 33, fmt3.str(), __FILE__, __LINE__ );
364         boost::format    fmt4( "active_count = %d" );
365         fmt4 % active_count.get();
366         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 34, fmt4.str(), __FILE__, __LINE__ );
367     }
368
369     session_thread_control* tmp_stc_ptr = waiting_sessions.find( stc_ptr_noconst->get_session().get() );
370     waiting_sessions.erase( tmp_stc_ptr->get_session().get() );
371
372     stc_ptr_noconst->startupstream();
373     stc_ptr_noconst->startdownstream();
374
375     //waiting, pool_sessions.size become over 1
376     //pick up session from pool
377     session_thread_control*        stc_ptr_register_accept;
378     do{
379         stc_ptr_register_accept = pool_sessions.pop();
380     }
381     while( unlikely( !stc_ptr_register_accept ) );
382
383     //session add wait_sessions
384     boost::mutex::scoped_lock    up_wait_lk( stc_ptr_register_accept->get_upthread_mutex() );
385     boost::mutex::scoped_lock    down_wait_lk( stc_ptr_register_accept->get_downthread_mutex() );
386
387     waiting_sessions.insert( stc_ptr_register_accept->get_session().get(), stc_ptr_register_accept );
388
389     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
390         boost::format    fmt1( "active session thread id = %d" );
391         fmt1 % stc_ptr_register_accept->get_upthread_id();
392         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 35, fmt1.str(), __FILE__, __LINE__ );
393         boost::format    fmt2( "pool_session.size   = %d" );
394         fmt2 % pool_sessions.size();
395         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 36, fmt2.str(), __FILE__, __LINE__ );
396         boost::format    fmt3( "active_session.size = %d" );
397         fmt3 % active_sessions.size();
398         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 37, fmt3.str(), __FILE__, __LINE__ );
399         boost::format    fmt4( "active_count = %d" );
400         fmt4 % active_count.get();
401         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 38, fmt4.str(), __FILE__, __LINE__ );
402     }
403
404     //regist accept event handler
405     if (!ssl_virtualservice_mode_flag) {
406         acceptor_.async_accept( stc_ptr_register_accept->get_session()->get_client_socket(),
407                     boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr_register_accept, boost::asio::placeholders::error ) );
408     } else {
409         acceptor_.async_accept( stc_ptr_register_accept->get_session()->get_client_ssl_socket().lowest_layer(),
410                     boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr_register_accept, boost::asio::placeholders::error ) );
411     }
412
413     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
414         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 39, "out_function : void virtualservice_tcp::handle_accept( const boost::shared_ptr<session_thread_control> , const boost::system::error_code& err )", __FILE__, __LINE__ );
415     }
416 }
417
418 /*!
419  * initialize virtualservice(TCP)
420  *
421  * @param   erro_code
422  * @return  void
423  */
424 void    l7vs::virtualservice_tcp::initialize( l7vs::error_code& err ){
425     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
426         boost::format formatter("in_function : void virtualservice_tcp::initialize( "
427                                 "l7vs::error_code& err )");
428         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 40, formatter.str(), __FILE__, __LINE__ );
429     }
430     if( pool_sessions.size() != 0 ){
431         err.setter( true, "VirtualService already initialized." );
432         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
433             boost::format formatter("out_function : void virtualservice_tcp::initialize( "
434                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
435             formatter % ( err ? "true" : "false") % err.get_message();
436             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 41, formatter.str(), __FILE__, __LINE__ );
437         }
438         return;
439     }
440
441     //load parameter value
442     load_parameter( err );
443     if( err ){
444         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
445             boost::format formatter("out_function : void virtualservice_tcp::initialize( "
446                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
447             formatter % ( err ? "true" : "false") % err.get_message();
448             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 42, formatter.str(), __FILE__, __LINE__ );
449         }
450         return;
451     }
452
453     // access log flag and access log file name setting contents check.
454     if( element.access_log_flag == 1 && element.access_log_file_name == "" ) {
455         boost::format formatter("access log file name not set error");
456         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 3, formatter.str(), __FILE__, __LINE__ );
457         err.setter( true, "access log file name not set error" );
458         return;
459     }
460
461     logger_implement_access *access_log_instance = NULL;
462     // access log instance create.
463     if( element.access_log_file_name != "" ) {
464         access_log_instance 
465                         = logger_access_manager::getInstance().find_logger_implement_access( 
466                                                                     element.access_log_file_name, 
467                                                                     element.access_log_rotate_arguments, 
468                                                                     err );
469         if( access_log_instance == NULL ) {
470             boost::format formatter("access logger Instance acquisition err = %s, err.message = %s ");
471             formatter % ( err ? "true" : "false") % err.get_message();
472             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 4, formatter.str(), __FILE__, __LINE__ );
473             err.setter( true, "access log class instance create failed" );
474             return;
475         }
476     }
477
478     //get cpumask
479     boost::asio::ip::address    address    = element.tcp_accept_endpoint.address();
480 #ifdef    SCHED_SETAFFINITY
481     vsnic_cpumask    = get_cpu_mask( address );
482     rsnic_cpumask    = get_cpu_mask( param_data.nic_realserver_side );
483 #endif
484
485     //bind acceptor
486     boost::system::error_code    acceptor_err;
487     acceptor_.open( element.tcp_accept_endpoint.protocol(), acceptor_err );
488     if( acceptor_err ){
489         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 5, acceptor_err.message(), __FILE__, __LINE__ );
490         err.setter( true, acceptor_err.message() );
491         return;
492     }
493     acceptor_.set_option( boost::asio::ip::tcp::acceptor::reuse_address( true ), acceptor_err );
494     if( acceptor_err ){
495         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 6, acceptor_err.message(), __FILE__, __LINE__ );
496         err.setter( true, acceptor_err.message() );
497         return;
498     }
499     if( likely(address.is_v6()) ) {
500         boost::asio::ip::v6_only option(true);
501         acceptor_.set_option( option, acceptor_err );
502         if( acceptor_err ) {
503             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 7, acceptor_err.message(), __FILE__, __LINE__ );
504             err.setter( true, acceptor_err.message() );
505             return;
506         }
507     }
508     acceptor_.bind( element.tcp_accept_endpoint, acceptor_err );
509     if( acceptor_err ){
510         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 8, acceptor_err.message(), __FILE__, __LINE__ );
511         err.setter( true, acceptor_err.message() );
512         return;
513     }
514
515     //read replication data
516     read_replicationdata();
517
518     //load protocol module
519     protomod = protocol_module_control::getInstance().load_module( element.protocol_module_name );
520     if( NULL == protomod ){
521         //ERROR case
522         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 9, PROTOMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
523         err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
524         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
525             boost::format formatter("out_function : void virtualservice_tcp::initialize( "
526                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
527             formatter % ( err ? "true" : "false") % err.get_message();
528             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 43, formatter.str(), __FILE__, __LINE__ );
529         }
530         return;
531     }
532     //Protocol Module Initialize
533     protomod->init_logger_functions(
534                     boost::bind( &Logger::getLogLevel, LOG_CAT_PROTOCOL ),
535                     boost::bind( &Logger::putLogFatal, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
536                     boost::bind( &Logger::putLogError, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
537                     boost::bind( &Logger::putLogWarn, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
538                     boost::bind( &Logger::putLogInfo, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ),
539                     boost::bind( &Logger::putLogDebug, LOG_CAT_PROTOCOL, _1, _2, _3, _4 ) );
540     protomod->initialize(
541                     boost::bind( &virtualservice_tcp::rs_list_begin, this ),
542                     boost::bind( &virtualservice_tcp::rs_list_end, this ),
543                     boost::bind( &virtualservice_tcp::rs_list_next, this, _1 ),
544                     boost::bind( &virtualservice_tcp::rs_list_lock, this ),
545                     boost::bind( &virtualservice_tcp::rs_list_unlock, this ) );
546     protomod->init_replication_functions(
547                     boost::bind( &virtualservice_tcp::replication_pay_memory, this, _1, _2 ),
548                     boost::bind( &virtualservice_tcp::replication_area_lock, this, element.protocol_module_name ),
549                     boost::bind( &virtualservice_tcp::replication_area_unlock, this, element.protocol_module_name ),
550                     element.tcp_accept_endpoint,
551                     element.udp_recv_endpoint );
552     tcp_schedule_func_type    sched_rs_func    = boost::bind( &virtualservice_tcp::schedule_rs, this, _1, _2, _3, _4, _5 );
553     protomod->register_schedule( sched_rs_func );
554
555     protocol_module_base::check_message_result pm_result;
556     
557     pm_result    =    protomod->check_parameter( element.protocol_args );
558     if( !pm_result.flag ){
559         err.setter( true, "Protocol Module argument error." );
560         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
561             boost::format formatter("out_function : void virtualservice_tcp::initialize( "
562                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
563             formatter % ( err ? "true" : "false") % err.get_message();
564             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 44, formatter.str(), __FILE__, __LINE__ );
565         }
566         return;
567     }
568     pm_result    =    protomod->set_parameter( element.protocol_args );
569     if( !pm_result.flag ){
570         err.setter( true, "Protocol Module argument error." );
571         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
572             boost::format formatter("out_function : void virtualservice_tcp::initialize( "
573                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
574             formatter % ( err ? "true" : "false") % err.get_message();
575             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 45, formatter.str(), __FILE__, __LINE__ );
576         }
577         return;
578     }
579
580     protomod->get_option_info(protocol_module_for_indication_options);
581     element.protocol_module_for_indication_options = protocol_module_for_indication_options;
582
583     //load schedule module    
584     schedmod = schedule_module_control::getInstance().load_module( element.schedule_module_name );
585     if( NULL == schedmod ){
586         //ERROR case
587         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 10, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
588         err.setter( true, SCHEDMOD_LOAD_ERROR_MSG );
589         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
590             boost::format formatter("out_function : void virtualservice_tcp::initialize( "
591                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
592             formatter % ( err ? "true" : "false") % err.get_message();
593             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 46, formatter.str(), __FILE__, __LINE__ );
594         }
595         return;
596     }
597     //Schedule Module Initialize
598     schedmod->init_logger_functions(
599                     boost::bind( &Logger::getLogLevel, LOG_CAT_SCHEDULE ),
600                     boost::bind( &Logger::putLogFatal, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
601                     boost::bind( &Logger::putLogError, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
602                     boost::bind( &Logger::putLogWarn, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
603                     boost::bind( &Logger::putLogInfo, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ),
604                     boost::bind( &Logger::putLogDebug, LOG_CAT_SCHEDULE, _1, _2, _3, _4 ) );
605     schedmod->initialize();
606     schedmod->init_replication_functions(
607                     boost::bind( &virtualservice_tcp::replication_pay_memory, this, _1, _2 ),
608                     boost::bind( &virtualservice_tcp::replication_area_lock, this, element.schedule_module_name ),
609                     boost::bind( &virtualservice_tcp::replication_area_unlock, this, element.schedule_module_name ),
610                     element.tcp_accept_endpoint,
611                     element.udp_recv_endpoint );
612
613     // access log flag set 
614     access_log_flag = false;
615     if ( element.access_log_flag == 1 ) {
616         access_log_flag = true;
617     }
618
619     // access log rotation infomation set.
620     if ( element.access_log_rotate_key_info == "" ) {
621        element.access_log_rotate_key_info = "none";
622        element.access_log_rotate_verbose_info = logger_access_manager::getInstance().get_rotate_default_verbose_displayed_contents(); 
623     } else {
624         element.access_log_rotate_verbose_info = element.access_log_rotate_key_info;
625     }
626     access_log_file_name = element.access_log_file_name;
627     access_log_rotate_arguments = element.access_log_rotate_arguments;
628
629     // SSL setting
630     ssl_virtualservice_mode_flag = false;
631     ssl_file_name = element.ssl_file_name;
632     if ( ssl_file_name != "" ) {
633         ssl_file_name = element.ssl_file_name;
634         // get SSL parameter
635         if(unlikely(!get_ssl_parameter())) {
636             //Error
637             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 11, "get ssl parameter failed", __FILE__, __LINE__ );
638             err.setter( true, "get ssl parameter failed" );
639             return;
640         }
641         // set SSL configuration
642         if(unlikely(!set_ssl_config())) {
643             //Error
644             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 12, "set ssl config failed", __FILE__, __LINE__ );
645             err.setter( true, "set ssl config failed" );
646             return;
647         }
648         ssl_virtualservice_mode_flag = true;
649     }
650
651
652     set_socket_option();
653
654     //create session pool
655     {
656         for( int i = 0; i < param_data.session_pool_size; ++i ){
657             try{
658                 tcp_session*    sess    = new tcp_session(*this,
659                                       dispatcher,
660                                       set_sock_opt,
661                                       element.tcp_accept_endpoint,
662                                       ssl_virtualservice_mode_flag,
663                                       sslcontext,
664                                       is_session_cache_use,
665                                       handshake_timeout,
666                                       access_log_instance);
667                 session_result_message    result    = sess->initialize();
668                 if( result.flag == true ){
669                     err.setter( result.flag, result.message );
670                     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
671                         boost::format formatter("out_function : void virtualservice_tcp::initialize( "
672                                                 "l7vs::error_code& err ) : err = %s, err.message = %s");
673                         formatter % ( err ? "true" : "false") % err.get_message();
674                         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 47, formatter.str(), __FILE__, __LINE__ );
675                     }
676                     return;
677                 }
678                 session_thread_control*    p_stc = new session_thread_control( sess, vsnic_cpumask, rsnic_cpumask, -1 );
679                 while( !pool_sessions.push( p_stc ) ){}
680             }
681             catch( std::bad_alloc ex ){
682                 Logger::putLogFatal( 
683                     LOG_CAT_L7VSD_VIRTUALSERVICE, 1, "error, create session.", __FILE__, __LINE__ );
684                 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
685                     boost::format formatter("out_function : void virtualservice_tcp::initialize( "
686                                             "l7vs::error_code& err ) : err = %s, err.message = %s");
687                     formatter % ( err ? "true" : "false") % err.get_message();
688                     Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 48, formatter.str(), __FILE__, __LINE__ );
689                 }
690                 return;
691             }
692         }
693         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
694             boost::format    fmt1( "pool_session.size   = %d" );
695             fmt1 % pool_sessions.size();
696             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 49, fmt1.str(), __FILE__, __LINE__ );
697             boost::format    fmt2( "active_session.size = %d" );
698             fmt2 % active_sessions.size();
699             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 50, fmt2.str(), __FILE__, __LINE__ );
700         }
701     }
702
703     err.setter( false, "" );
704
705     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
706         boost::format formatter("out_function : void virtualservice_tcp::initialize( "
707                                 "l7vs::error_code& err ) : err = %s, err.message = %s");
708         formatter % ( err ? "true" : "false") % err.get_message();
709         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 51, formatter.str(), __FILE__, __LINE__ );
710     }
711 }
712
713 /*!
714  * finalize virtualservice(TCP)
715  *
716  * @param   erro_code
717  * @return  void
718  */
719 void        l7vs::virtualservice_tcp::finalize( l7vs::error_code& err ){
720     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
721         boost::format formatter("in_function : void virtualservice_tcp::finalize( "
722                                 "l7vs::error_code& err )");
723         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 52, formatter.str(), __FILE__, __LINE__ );
724
725         boost::format    fmt1( "pool_session.size   = %d" );
726         fmt1 % pool_sessions.size();
727         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 53, fmt1.str(), __FILE__, __LINE__ );
728         boost::format    fmt2( "active_session.size = %d" );
729         fmt2 % active_sessions.size();
730         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 54, fmt2.str(), __FILE__, __LINE__ );
731     }
732
733     //stop main loop
734     stop();
735
736     while(active_sessions.size()){
737         boost::this_thread::yield();
738     }
739
740     for(;;){
741         tcp_session*                tmp_session    = NULL;
742         session_thread_control*        tmp_stc        = NULL;
743         waiting_sessions.pop( tmp_session, tmp_stc );
744         if( !tmp_stc ){
745             break;
746         }
747         for(;;){
748             if( likely( pool_sessions.push( tmp_stc ) ) )break;
749         }
750     }
751
752     //release sessions[i]->join();
753     while( !pool_sessions.empty() ){
754         session_thread_control*    stc = pool_sessions.pop();
755         stc->join();
756         {
757             boost::mutex::scoped_lock upthread_wait( stc->get_upthread_mutex() );
758             boost::mutex::scoped_lock downthread_wait( stc->get_downthread_mutex() );
759         }
760         delete    stc;
761         stc = NULL;
762         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
763             boost::format    fmt( "join pool sessin : pool_sessions.size = %d" );
764             fmt % pool_sessions.size();
765             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 55, fmt.str(), __FILE__, __LINE__ );
766         }
767     }
768
769     //unload ProtocolModule
770     if( protomod ){
771         //finalize ProtocolModule
772         protomod->finalize();
773         //unload ProtocolModule
774         protocol_module_control::getInstance().unload_module( protomod );
775         protomod = NULL;
776     }
777     //unload ScheduleModule
778     if( schedmod ){
779         schedule_module_control::getInstance().unload_module( schedmod );
780         schedmod = NULL;
781     }
782
783     active_sessions.clear();
784     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
785         boost::format    fmt1( "pool_session.size   = %d" );
786         fmt1 % pool_sessions.size();
787         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 56, fmt1.str(), __FILE__, __LINE__ );
788         boost::format    fmt2( "active_session.size = %d" );
789         fmt2 % active_sessions.size();
790         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 57, fmt2.str(), __FILE__, __LINE__ );
791     }
792
793     //clear replication_data
794     bool    replication_status    = true;
795     replication&    rep_noconst = const_cast<replication&>( rep );
796
797     if( replication::REPLICATION_SINGLE != rep_noconst.get_status() ){
798         unsigned int    rep_size = 0;
799         replication_header*    rep_header_ptr = reinterpret_cast<replication_header*>( rep_noconst.pay_memory( REP_AREA_NAME, rep_size) );
800         if( (rep_header_ptr == NULL) || (0 == rep_size) ){
801             err.setter( true, REP_BLOCK_SIZE_ERR_MSG );
802             Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 6, REP_BLOCK_SIZE_ERR_MSG, __FILE__, __LINE__ );
803             replication_status = false;
804         }
805     
806         //check maxdatasize
807         if( ( rep_size * DATA_SIZE ) <
808             ((sizeof(replication_data) * MAX_REPLICATION_DATA_NUM) + sizeof(replication_header)) ){
809             err.setter( true, REP_AREA_SIZE_ERR_MSG );
810             Logger::putLogWarn( LOG_CAT_L7VSD_VIRTUALSERVICE, 7, REP_AREA_SIZE_ERR_MSG, __FILE__, __LINE__ );
811             replication_status = false;
812         }
813         if( (NULL != rep_header_ptr) && (replication_status) ){
814             //lock replication area
815             rep_noconst.lock( REP_AREA_NAME );
816             //set data_num = 0
817             rep_header_ptr->data_num = 0;
818             //unlock replication area
819             rep_noconst.unlock( REP_AREA_NAME );
820         }
821     }
822
823     vsd.release_virtual_service( element );
824
825     if( access_log_file_name != "" ) {
826         // erase access log instance.
827         logger_access_manager::getInstance().erase_logger_implement_access( access_log_file_name, err );
828         if ( unlikely(err) ) {
829             boost::format    fmt( "access logger instance erase err:%s" );
830             fmt % err.get_message();
831             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 8,
832                                    fmt.str(),
833                                    __FILE__, __LINE__ );
834         }
835     }
836     
837     err.setter( false, "" );
838
839     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
840         boost::format formatter("out_function : void virtualservice_tcp::finalize( "
841                                 "l7vs::error_code& err ) : err = %s, err.message = %s");
842         formatter % ( err ? "true" : "false") % err.get_message();
843         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 58, formatter.str(), __FILE__, __LINE__ );
844     }
845
846 }
847
848 /*!
849  * equal compare virtualservice(TCP)
850  *
851  * @param   virtualservice_base
852  * @return  bool ( true = equal )
853  */
854 bool    l7vs::virtualservice_tcp::operator==( const l7vs::virtualservice_base& in ){
855     boost::format formatter("function : void virtualservice_tcp::operator==( "
856                             "const l7vs::virtualservice_base& in )");
857     Logger    funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 59, formatter.str(), __FILE__, __LINE__ );
858
859     virtualservice_base&    vs = const_cast<virtualservice_base&>( in );
860     return (    ( element.tcp_accept_endpoint == vs.get_element().tcp_accept_endpoint )
861             &&    ( element.udpmode == vs.get_element().udpmode ) );
862 }
863
864 /*!
865  * not-equal compare virtualservice(TCP)
866  *
867  * @param   virtualservice_base
868  * @return  bool ( true = not-equal )
869  */
870 bool    l7vs::virtualservice_tcp::operator!=( const l7vs::virtualservice_base& in ){
871     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
872         boost::format formatter("in/out_function : void virtualservice_tcp::operator!=( "
873                                 "const l7vs::virtualservice_base& in )");
874         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 60, formatter.str(), __FILE__, __LINE__ );
875     }
876     virtualservice_base&    vs = const_cast<virtualservice_base&>( in );
877     return (    ( element.tcp_accept_endpoint != vs.get_element().tcp_accept_endpoint )
878             ||    ( element.udpmode != vs.get_element().udpmode ) );
879 }
880
881 /*!
882  * add VirtualService( not-imprement )
883  *
884  * @param   virtualservice_element
885  * @param   err
886  * @return  void
887  */
888 void    l7vs::virtualservice_tcp::set_virtualservice( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
889     err.setter( false, "" );
890 }
891
892 /*!
893  * edit VirtualService
894  *
895  * @param   virtualservice_element
896  * @param   err
897  * @return  void
898  */
899 void    l7vs::virtualservice_tcp::edit_virtualservice( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
900     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
901         boost::format formatter("in_function : void virtualservice_tcp::edit_virtualservice( "
902                                 "const l7vs::virtualservice_element& in,"
903                                 "l7vs::error_code& err ) : dump in ");
904         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 61, formatter.str(), __FILE__, __LINE__ );
905     }
906
907     virtualservice_element&    elem = const_cast<virtualservice_element&>( in );
908     //繝代Λ繝。繝シ繧ソ縺祁irtualService縺ォ荳\80閾エ縺吶k縺区、懈渊
909     //udpmode縺ィtcp_accept_endpoint縺ィprotocol_module_name縺御ク\80閾エ縺吶k縺薙→
910     if( ( element.udpmode != elem.udpmode ) ||
911         ( element.tcp_accept_endpoint != elem.tcp_accept_endpoint ) ||
912         ( element.protocol_module_name != elem.protocol_module_name ) ){
913         err.setter( true, "Virtual Service does not exist." );
914         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
915             boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
916                                     "const l7vs::virtualservice_element& in,"
917                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
918             formatter % ( err ? "true" : "false") % err.get_message();
919             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 62, formatter.str(), __FILE__, __LINE__ );
920         }
921         return;
922     }
923
924     //if change ScueduleModule Name, unload old ScheduleModule and load new ScheduleModule
925     if( ( element.schedule_module_name != elem.schedule_module_name ) && ( "" != elem.schedule_module_name ) ){
926         schedule_module_control::getInstance().unload_module( schedmod );
927         schedmod = schedule_module_control::getInstance().load_module( elem.schedule_module_name );
928         if( NULL == schedmod ){
929             //ERROR case
930             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 13, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
931             err.setter( true, SCHEDMOD_LOAD_ERROR_MSG );
932             if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
933                 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
934                                         "const l7vs::virtualservice_element& in,"
935                                         "l7vs::error_code& err ) : err = %s, err.message = %s");
936                 formatter % ( err ? "true" : "false") % err.get_message();
937                 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 63, formatter.str(), __FILE__, __LINE__ );
938             }
939             return;
940         }
941         element.schedule_module_name = elem.schedule_module_name;
942     }
943 /*
944     //additional PM options(for protomod_url)
945     protocol_module_base::check_message_result result;
946     if( NULL != protomod ){
947         result = protomod->add_parameter( elem.protocol_args );
948         if( result.flag ){
949             for( size_t i = 0; i < elem.protocol_args.size(); ++i ){
950                 element.protocol_args.push_back( elem.protocol_args[i] );
951             }
952         }else{
953             err.setter( true, result.message );
954             if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
955                 boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
956                                         "const l7vs::virtualservice_element& in,"
957                                         "l7vs::error_code& err ) : err = %s, err.message = %s");
958                 formatter % ( err ? "true" : "false") % err.get_message();
959                 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 64, formatter.str(), __FILE__, __LINE__ );
960             }
961             return;
962         }
963     }else{
964         //ERROR case
965         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 14, PROTOMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
966         err.setter( true, PROTOMOD_LOAD_ERROR_MSG );
967         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
968             boost::format formatter("out_function : void virtualservice_tcp::edit_virtualservice( "
969                                     "const l7vs::virtualservice_element& in,"
970                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
971             formatter % ( err ? "true" : "false") % err.get_message();
972             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 65, formatter.str(), __FILE__, __LINE__ );
973         }
974         return;
975     }
976 */
977     //update values
978     //qos_upstream;
979     if( ULLONG_MAX == elem.qos_upstream )
980         element.qos_upstream    = 0ULL;
981     else if( 0ULL != elem.qos_upstream )
982         element.qos_upstream    = elem.qos_upstream;
983     //qos_downstream;
984     if( ULLONG_MAX == elem.qos_downstream )
985         element.qos_downstream    = 0ULL;
986     else if( 0ULL != elem.qos_downstream )
987         element.qos_downstream    = elem.qos_downstream;
988     //sorry_maxconnection;
989     if( LLONG_MAX == elem.sorry_maxconnection )
990         element.sorry_maxconnection    = 0;
991     else if( 0 != elem.sorry_maxconnection )
992         element.sorry_maxconnection    = elem.sorry_maxconnection;
993     //sorry_flag;
994     if( INT_MAX == elem.sorry_flag )
995         element.sorry_flag            = 0;
996     else if( 0 != elem.sorry_flag )
997         element.sorry_flag            = 1;
998     //sorry_endpoint;
999     //if endpoint of SorryServer equal 255.255.255.255:0,not update
1000     //if equal endpoint 255.255.255.255:0, clear sorry parameters
1001     if( elem.sorry_endpoint ==
1002             boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "255.255.255.255" ), (0)) ){
1003         element.sorry_endpoint            = boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "0.0.0.0" ), (0) );
1004         element.sorry_maxconnection    = 0LL;
1005         element.sorry_flag            = false;
1006         active_sessions.do_all( boost::bind( &session_thread_control::session_sorry_disable, _1 ) );
1007     }else{
1008         if( elem.sorry_endpoint !=
1009                 boost::asio::ip::tcp::endpoint( boost::asio::ip::address::from_string( "0.0.0.0" ), (0) ) )
1010             element.sorry_endpoint        = elem.sorry_endpoint;
1011
1012         active_sessions.do_all( boost::bind( &session_thread_control::session_sorry_mode_change, _1, elem.sorry_flag ) );
1013     }
1014
1015     // access log flag ON and access log filename not set.
1016     if ( elem.access_log_flag == 1 && element.access_log_file_name == "" ) {
1017         //ERROR case
1018         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 15, SCHEDMOD_LOAD_ERROR_MSG, __FILE__, __LINE__ );
1019         err.setter( true, "access log flag change err." );
1020         return;
1021     }
1022
1023     // access log flag check and send access log output ON or OFF message to tcp_session
1024     element.access_log_flag = elem.access_log_flag;
1025     if (elem.access_log_flag==1 && access_log_flag==false ) {
1026         active_sessions.do_all( boost::bind( &session_thread_control::session_accesslog_output_mode_on, _1 ) );
1027         access_log_flag = true;
1028     } else if ( elem.access_log_flag==0 && access_log_flag==true ) {
1029         active_sessions.do_all( boost::bind( &session_thread_control::session_accesslog_output_mode_off, _1 ) );
1030         access_log_flag = false;
1031     }
1032
1033     err.setter( false, "" );
1034
1035     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1036         boost::format formatter("out_function : void virtualservice_tcp::set_virtualservice( "
1037                                 "const l7vs::virtualservice_element& in,"
1038                                 "l7vs::error_code& err ) : err = %s, err.message = %s");
1039         formatter % ( err ? "true" : "false") % err.get_message();
1040         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 66, formatter.str(), __FILE__, __LINE__ );
1041     }
1042 }
1043
1044 /*!
1045  * add realserver
1046  *
1047  * @param   virtualservice_element
1048  * @param   err
1049  * @return  void
1050  */
1051 void    l7vs::virtualservice_tcp::add_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1052     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1053         boost::format formatter("in_function : void virtualservice_tcp::add_realserver( "
1054                                 "const l7vs::virtualservice_element& in,"
1055                                 "l7vs::error_code& err )");
1056         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 67, formatter.str(), __FILE__, __LINE__ );
1057     }
1058
1059     virtualservice_element&    in_element = const_cast<virtualservice_element&>( in );
1060
1061     //check equal virtualservice
1062     if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1063         err.setter( true, "Virtual Service does not exist." );
1064         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1065             boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1066                                     "const l7vs::virtualservice_element& in,"
1067                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
1068             formatter % ( err ? "true" : "false") % err.get_message();
1069             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 68, formatter.str(), __FILE__, __LINE__ );
1070         }
1071         return;
1072     }    
1073     //check rs num
1074     if( in.realserver_vector.size() == 0U ){
1075         err.setter( true, "." );
1076         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1077             boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1078                                     "const l7vs::virtualservice_element& in,"
1079                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
1080             formatter % ( err ? "true" : "false") % err.get_message();
1081             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 69, formatter.str(), __FILE__, __LINE__ );
1082         }
1083         return;
1084     }
1085     //lock rs_list_ref_count_inc_mutex
1086     rw_scoped_lock    inc_lock( rs_list_ref_count_inc_mutex );
1087
1088     //waiting, rs_list_ref_count become 0
1089     boost::xtime        interval;
1090     boost::mutex        mtx;
1091     boost::condition    cond;
1092
1093     interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1094     boost::mutex::scoped_lock lk( mtx );
1095     while( rs_list_ref_count != 0ULL ){
1096         cond.timed_wait( lk, interval );
1097     }
1098
1099     //check duplication realserver
1100     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1101          itr != in_element.realserver_vector.end();
1102          ++itr ){
1103         for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1104              rs_itr != rs_list.end(); ++rs_itr ){
1105             if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1106                 err.setter( true, "Real Server already exist." );
1107                 if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1108                     boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1109                                             "const l7vs::virtualservice_element& in,"
1110                                             "l7vs::error_code& err ) : err = %s, err.message = %s");
1111                     formatter % ( err ? "true" : "false") % err.get_message();
1112                     Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 70, formatter.str(), __FILE__, __LINE__ );
1113                 }
1114                 return;
1115             }
1116         }
1117     }
1118
1119     //pause active sessions
1120     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1121
1122     //add realserver
1123     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1124          itr != in_element.realserver_vector.end();
1125          ++itr ){
1126         realserver    rs;
1127         rs.tcp_endpoint        = itr->tcp_endpoint;
1128         rs.udp_endpoint        = itr->udp_endpoint;
1129         rs.weight            = itr->weight;
1130         rs_list.push_back( rs );
1131     }
1132
1133     //run active sessions
1134     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1135
1136     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1137         boost::format formatter("out_function : void virtualservice_tcp::add_realserver( "
1138                                 "const l7vs::virtualservice_element& in,"
1139                                 "l7vs::error_code& err ) : err = %s, err.message = %s");
1140         formatter % ( err ? "true" : "false") % err.get_message();
1141         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 71, formatter.str(), __FILE__, __LINE__ );
1142     }
1143 }
1144
1145 /*!
1146  * edit realserver
1147  *
1148  * @param   virtualservice_element
1149  * @param   err
1150  * @return  void
1151  */
1152 void    l7vs::virtualservice_tcp::edit_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1153     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1154         boost::format formatter("in_function : void virtualservice_tcp::edit_realserver( "
1155                                 "const l7vs::virtualservice_element& in,"
1156                                 "l7vs::error_code& err )");
1157         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 72, formatter.str(), __FILE__, __LINE__ );
1158     }
1159     //check equal virtualservice
1160     if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1161         err.setter( true, "Virtual Service does not exist." );
1162         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1163             boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1164                                     "const l7vs::virtualservice_element& in,"
1165                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
1166             formatter % ( err ? "true" : "false") % err.get_message();
1167             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 73, formatter.str(), __FILE__, __LINE__ );
1168         }
1169         return;
1170     }    
1171
1172     //lock rs_list_ref_count_inc_mutex
1173     rw_scoped_lock    inc_lock( rs_list_ref_count_inc_mutex );
1174
1175     //waiting, rs_list_ref_count become 0
1176     boost::xtime        interval;
1177     boost::mutex        mtx;
1178     boost::condition    cond;
1179
1180     interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1181     boost::mutex::scoped_lock lk( mtx );
1182     while( rs_list_ref_count != 0ULL ){
1183         cond.timed_wait( lk, interval );
1184     }
1185
1186     virtualservice_element&    in_element = const_cast<virtualservice_element&>( in );
1187
1188     //check is exist realserver
1189     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1190          itr != in_element.realserver_vector.end();
1191          ++itr ){
1192         bool    exist_flag = false;
1193         for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1194              rs_itr != rs_list.end(); ++rs_itr ){
1195             if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1196                 exist_flag = true;
1197             }
1198         }
1199         if( !exist_flag ){
1200             err.setter( true, "Real Server does not exist." );
1201             if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1202                 boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1203                                         "const l7vs::virtualservice_element& in,"
1204                                         "l7vs::error_code& err ) : err = %s, err.message = %s");
1205                 formatter % ( err ? "true" : "false") % err.get_message();
1206                 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 74, formatter.str(), __FILE__, __LINE__ );
1207             }
1208             return;
1209         }
1210     }
1211
1212     //pause active sessions
1213     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1214
1215     //edit realserver
1216     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1217          itr != in_element.realserver_vector.end();
1218          ++itr ){
1219         for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1220              rs_itr != rs_list.end(); ++rs_itr ){
1221             if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1222                 rs_itr->udp_endpoint    = itr->udp_endpoint;
1223
1224                 if( itr->weight != -1 ) {
1225                     rs_itr->weight            = itr->weight;
1226                 }
1227
1228             }
1229         }
1230     }
1231
1232     //run active sessions
1233     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1234
1235     err.setter( false, "" );
1236     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1237         boost::format formatter("out_function : void virtualservice_tcp::edit_realserver( "
1238                                 "const l7vs::virtualservice_element& in,"
1239                                 "l7vs::error_code& err ) : err = %s, err.message = %s");
1240         formatter % ( err ? "true" : "false") % err.get_message();
1241         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 75, formatter.str(), __FILE__, __LINE__ );
1242     }
1243 }
1244
1245 /*!
1246  * delete realserver
1247  *
1248  * @param   virtualservice_element
1249  * @param   err
1250  * @return  void
1251  */
1252 void    l7vs::virtualservice_tcp::del_realserver( const l7vs::virtualservice_element& in, l7vs::error_code& err ){
1253     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1254         boost::format formatter("in_function : void virtualservice_tcp::del_realserver( "
1255                                 "const l7vs::virtualservice_element& in,"
1256                                 "l7vs::error_code& err )");
1257         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 76, formatter.str(), __FILE__, __LINE__ );
1258     }
1259
1260     //check equal virtualservice
1261     if( (element.udpmode != in.udpmode) || (element.tcp_accept_endpoint != in.tcp_accept_endpoint) ){
1262         err.setter( true, "Virtual Service is not equal." );
1263         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1264             boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1265                                     "const l7vs::virtualservice_element& in,"
1266                                     "l7vs::error_code& err ) : err = %s, err.message = %s");
1267             formatter % ( err ? "true" : "false") % err.get_message();
1268             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 77, formatter.str(), __FILE__, __LINE__ );
1269         }
1270         return;
1271     }    
1272
1273     //lock rs_list_ref_count_inc_mutex
1274     rw_scoped_lock    inc_lock( rs_list_ref_count_inc_mutex );
1275
1276     //waiting, rs_list_ref_count become 0
1277     boost::xtime        interval;
1278     boost::mutex        mtx;
1279     boost::condition    cond;
1280
1281     interval.nsec = virtualservice_base::REFCOUNT_WAIT_INTERVAL;
1282     boost::mutex::scoped_lock lk( mtx );
1283     while( rs_list_ref_count != 0ULL ){
1284         cond.timed_wait( lk, interval );
1285     }
1286
1287     virtualservice_element&    in_element = const_cast<virtualservice_element&>( in );
1288
1289     //check is exist realserver
1290     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1291          itr != in_element.realserver_vector.end();
1292          ++itr ){
1293         bool    exist_flag = false;
1294         for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1295              rs_itr != rs_list.end(); ++rs_itr ){
1296             if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1297                 exist_flag = true;
1298             }
1299         }
1300         if( !exist_flag ){
1301             err.setter( true, "Real Server does not exist." );
1302             if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1303                 boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1304                                         "const l7vs::virtualservice_element& in,"
1305                                         "l7vs::error_code& err ) : err = %s, err.message = %s");
1306                 formatter % ( err ? "true" : "false") % err.get_message();
1307                 Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 78, formatter.str(), __FILE__, __LINE__ );
1308             }
1309             return;
1310         }
1311     }
1312
1313     //pause active sessions
1314     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_on, _1) );
1315
1316     //del realserver
1317     for( std::vector<realserver_element>::iterator itr = in_element.realserver_vector.begin();
1318          itr != in_element.realserver_vector.end();
1319          ++itr ){
1320         for( std::list<realserver>::iterator rs_itr = rs_list.begin();
1321              rs_itr != rs_list.end(); ++rs_itr ){
1322             if( itr->tcp_endpoint == rs_itr->tcp_endpoint ){
1323                 rs_list.erase( rs_itr );
1324                 break;
1325             }
1326         }
1327     }
1328
1329     //run active sessions
1330     active_sessions.do_all( boost::bind( &session_thread_control::session_pause_off, _1) );
1331
1332     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1333         boost::format formatter("out_function : void virtualservice_tcp::del_realserver( "
1334                                 "const l7vs::virtualservice_element& in,"
1335                                 "l7vs::error_code& err ) : err = %s, err.message = %s");
1336         formatter % ( err ? "true" : "false") % err.get_message();
1337         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 79, formatter.str(), __FILE__, __LINE__ );
1338     }
1339 }
1340
1341 /*!
1342  * main loop of virtualservice(TCP)
1343  *
1344  * @param   void
1345  * @return  void
1346  */
1347 void    l7vs::virtualservice_tcp::run(){
1348     Logger    funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 80, "function : void virtualservice_tcp::run()", __FILE__, __LINE__ );
1349
1350     if( pool_sessions.size() == 0 ){
1351         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 16, "VirtualService not initialized.", __FILE__, __LINE__ );
1352         return;
1353     }
1354     boost::asio::socket_base::receive_buffer_size option(8192 * 192);
1355     acceptor_.set_option(option);
1356     //set socket option TCP_DEFER_ACCEPT
1357     if(defer_accept_opt){
1358         boost::system::error_code ec;
1359         size_t len = sizeof(defer_accept_val);
1360         boost::asio::detail::socket_ops::setsockopt(acceptor_.native(),IPPROTO_TCP,TCP_DEFER_ACCEPT,&defer_accept_val,len,ec);
1361         if(unlikely(ec)){
1362             //ERROR
1363             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 17, "socket option(TCP_DEFER_ACCEPT) set failed" , __FILE__, __LINE__ );
1364         }
1365     }
1366     //start listen
1367     acceptor_.listen();
1368
1369     //switch active a session
1370     session_thread_control*    stc_ptr;
1371     {
1372         stc_ptr = pool_sessions.pop();
1373         if( !stc_ptr ){
1374             return;
1375         }
1376         //regist accept event handler
1377         waiting_sessions.insert( stc_ptr->get_session().get(), stc_ptr );
1378     }
1379     if (!ssl_virtualservice_mode_flag) {
1380         acceptor_.async_accept( stc_ptr->get_session()->get_client_socket(),
1381                         boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr, boost::asio::placeholders::error ) );
1382     } else {
1383         acceptor_.async_accept( stc_ptr->get_session()->get_client_ssl_socket().lowest_layer(),
1384                         boost::bind( &virtualservice_tcp::handle_accept, this, stc_ptr, boost::asio::placeholders::error ) );
1385     }
1386     //regist timer event handler
1387     calc_bps_timer->expires_from_now( boost::posix_time::milliseconds( param_data.bps_interval ) );
1388     calc_bps_timer->async_wait( boost::bind( &virtualservice_tcp::handle_throughput_update, 
1389                                              this, boost::asio::placeholders::error ) );
1390
1391     //register handle_replication_interrupt
1392     replication_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1393     replication_timer->async_wait( boost::bind( &virtualservice_tcp::handle_replication_interrupt, 
1394                                              this, boost::asio::placeholders::error ) );
1395     //register handle_protomod_replication
1396     protomod_rep_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1397     protomod_rep_timer->async_wait( boost::bind( &virtualservice_tcp::handle_protomod_replication, 
1398                                              this, boost::asio::placeholders::error ) );
1399     //register handle_schedmod_replication
1400     schedmod_rep_timer->expires_from_now( boost::posix_time::milliseconds( param_data.rep_interval ) );
1401     schedmod_rep_timer->async_wait( boost::bind( &virtualservice_tcp::handle_schedmod_replication, 
1402                                              this, boost::asio::placeholders::error ) );
1403
1404     //run dispatcher(start io_service loop)
1405     dispatcher.run();
1406
1407     //stop all active sessions
1408     {
1409         active_sessions.do_all( boost::bind( &session_thread_control::session_stop, _1 ) );
1410     }
1411 }
1412
1413 /*!
1414  * stop loop
1415  *
1416  * @param   void
1417  * @return  void
1418  */
1419 void    l7vs::virtualservice_tcp::stop(){
1420     Logger    funcLog( LOG_CAT_L7VSD_VIRTUALSERVICE, 81, "function : void virtualservice_tcp::stop()", __FILE__, __LINE__ );
1421
1422     boost::system::error_code    err;
1423
1424     acceptor_.close( err );
1425     if( err ){
1426         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 18, err.message(), __FILE__, __LINE__ );
1427     }
1428
1429     //stop dispatcher
1430     dispatcher.stop();
1431 }
1432
1433 /*!
1434  * increment active-connection count
1435  *
1436  * @param   endpoint
1437  * @return  void
1438  */
1439 void    l7vs::virtualservice_tcp::connection_active( const boost::asio::ip::tcp::endpoint& in ){
1440     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1441         boost::format formatter("in_function : void virtualservice_tcp::connection_active( "
1442                                 "const boost::asio::ip::tcp::endpoint& in ) : in = %s");
1443         formatter % in;
1444         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 82, formatter.str(), __FILE__, __LINE__ );
1445     }
1446     rs_list_lock();
1447     for( std::list<realserver>::iterator itr = rs_list.begin();
1448          itr != rs_list.end();
1449          ++itr ){
1450         if( itr->tcp_endpoint == in ){
1451             itr->increment_active();
1452             break;
1453         }
1454     }
1455     rs_list_unlock();
1456     active_count++;
1457
1458     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1459         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 83, "out_function : void virtualservice_tcp::connection_active()", __FILE__, __LINE__ );
1460     }
1461 }
1462
1463 /*!
1464  * increment in-active-connection (and decrement active-connection count)
1465  *
1466  * @param   endpoint
1467  * @return  void
1468  */
1469 void    l7vs::virtualservice_tcp::connection_inactive( const boost::asio::ip::tcp::endpoint& in ){
1470     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1471         boost::format formatter("in_function : void virtualservice_tcp::connection_inactive( "
1472                                 "const boost::asio::ip::tcp::endpoint& in ) : in = %s");
1473         formatter % in;
1474         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 84, formatter.str(), __FILE__, __LINE__ );
1475     }
1476     rs_list_lock();
1477     for( std::list<realserver>::iterator itr = rs_list.begin();
1478          itr != rs_list.end();
1479          ++itr ){
1480         if( itr->tcp_endpoint == in ){
1481             itr->decrement_active();
1482             itr->increment_inact();
1483             break;
1484         }
1485     }
1486     rs_list_unlock();
1487     active_count--;
1488
1489     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1490         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 85, "out_function : void virtualservice_tcp::connection_inactive()", __FILE__, __LINE__ );
1491     }
1492 }
1493
1494 /*!
1495  * release_session
1496  *
1497  * @param   void
1498  * @return  void
1499  */
1500 void    l7vs::virtualservice_tcp::release_session( const tcp_session* session_ptr ){
1501     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1502         boost::format funclog_fmt("in_function : void virtualservice_tcp::release_session( "
1503                                 "const tcp_session* session_ptr ) : session_ptr = %d");
1504         funclog_fmt % session_ptr;
1505         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 86, funclog_fmt.str(), __FILE__, __LINE__ );
1506     }
1507
1508     session_thread_control*        stc_ptr = active_sessions.find( session_ptr );
1509     if( unlikely( NULL == stc_ptr ) ){
1510         if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1511             boost::format    fmt( "session release fail : active_sessions.find( const tcp_session* session_ptr = %d )");
1512             fmt % session_ptr;
1513             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 87, fmt.str(), __FILE__, __LINE__ );
1514             Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 88, "out_function : void virtualservice_tcp::release_session( const boost::thread::id thread_id )", __FILE__, __LINE__ );
1515         }
1516         return;
1517     }
1518
1519     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1520         boost::format    fmt1( "pool_session.size   = %d" );
1521         fmt1 % pool_sessions.size();
1522         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 89, fmt1.str(), __FILE__, __LINE__ );
1523         boost::format    fmt2( "active_session.size = %d" );
1524         fmt2 % active_sessions.size();
1525         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 90, fmt2.str(), __FILE__, __LINE__ );
1526         boost::format    fmt3( "active_count = %d" );
1527         fmt3 % active_count.get();
1528         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 91, fmt3.str(), __FILE__, __LINE__ );
1529     }
1530     active_sessions.erase( session_ptr );
1531     stc_ptr->get_session()->initialize();
1532     for(;;){
1533         if( likely( pool_sessions.push( stc_ptr ) ) ){
1534             break;
1535         }
1536     }
1537
1538     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1539         boost::format    fmt1( "pool_session.size   = %d" );
1540         fmt1 % pool_sessions.size();
1541         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 92, fmt1.str(), __FILE__, __LINE__ );
1542         boost::format    fmt2( "active_session.size = %d" );
1543         fmt2 % active_sessions.size();
1544         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 93, fmt2.str(), __FILE__, __LINE__ );
1545         boost::format    fmt3( "active_count = %d" );
1546         fmt3 % active_count.get();
1547         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 94, fmt3.str(), __FILE__, __LINE__ );
1548
1549         boost::format funclog_fmt("out_function : void virtualservice_tcp::release_session( "
1550                                 "const tcp_session* session_ptr ) : session_ptr = %d");
1551         funclog_fmt % session_ptr;
1552         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 95, funclog_fmt.str(), __FILE__, __LINE__ );
1553     }
1554 }
1555
1556 //!
1557 // set_socket_option
1558 // @return  void
1559 void l7vs::virtualservice_tcp::set_socket_option(){
1560
1561     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1562         boost::format funclog_fmt("in_function : void virtualservice_tcp::et_socket_option");
1563         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 96, funclog_fmt.str(), __FILE__, __LINE__ );
1564     }
1565  
1566     // socket option check & set
1567     //! is set option TCP_DEFER_ACCEPT
1568     defer_accept_opt = false;
1569         //! TCP_DEFER_ACCEPT option value
1570     defer_accept_val = 0;
1571         
1572         //! TCP_NODELAY   (false:not set,true:set option)
1573     set_sock_opt.nodelay_opt = false;
1574         //! TCP_NODELAY option value  (false:off,true:on)
1575     set_sock_opt.nodelay_val = false;
1576         //! TCP_CORK      (false:not set,true:set option)
1577     set_sock_opt.cork_opt = false;
1578         //! TCP_CORK option value     (false:off,true:on)
1579     set_sock_opt.cork_val = false;
1580         //! TCP_QUICKACK  (false:not set,true:set option)
1581     set_sock_opt.quickack_opt = false;
1582         //! TCP_QUICKACK option value (false:off,true:on)
1583     set_sock_opt.quickack_val = false;
1584
1585     // set socket option
1586     if ( element.socket_option_tcp_defer_accept != 0 ) {
1587         defer_accept_opt = true;
1588         if ( element.socket_option_tcp_defer_accept == 1 ) {
1589             defer_accept_val = 1;
1590         }
1591     }
1592
1593     if ( element.socket_option_tcp_nodelay != 0 ) {
1594         set_sock_opt.nodelay_opt = true;
1595         if ( element.socket_option_tcp_nodelay == 1 ) {
1596             set_sock_opt.nodelay_val = true;
1597         }
1598     }
1599
1600     if ( element.socket_option_tcp_cork != 0 ) {
1601         set_sock_opt.cork_opt = true;
1602         if ( element.socket_option_tcp_cork == 1 ) {
1603             set_sock_opt.cork_val = true;
1604         }
1605     }
1606
1607     if ( element.socket_option_tcp_quickack != 0  ) {
1608         
1609         set_sock_opt.quickack_opt = true;
1610         if ( element.socket_option_tcp_quickack == 1  ) {
1611             set_sock_opt.quickack_val = true;
1612         }
1613     }
1614
1615     //----Debug log----------------------------------------------------------------------
1616     if( unlikely( LOG_LV_DEBUG == Logger::getLogLevel( LOG_CAT_L7VSD_VIRTUALSERVICE ) ) ){
1617         boost::format formatter("set_socket_option"
1618                     " defer_accept_opt[%s] defer_accept_val[%d]"
1619                     " nodelay_opt[%s] nodelay_val[%s]"
1620                     " cork_opt[%s] cork_val[%s]"
1621                     " quickack_opt[%s]" "quickack_val[%s]");
1622         formatter %(defer_accept_opt ? "true" : "false") %defer_accept_val 
1623                         %(set_sock_opt.nodelay_opt ? "true" : "false") %(set_sock_opt.nodelay_val ? "true" : "false") 
1624                         %(set_sock_opt.cork_opt ? "true" : "false") %(set_sock_opt.cork_val ? "true" : "false") 
1625                         %(set_sock_opt.quickack_opt ? "true" : "false") %(set_sock_opt.quickack_val ? "true" : "false");
1626         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 97, formatter.str(), __FILE__, __LINE__ );
1627     }
1628     //----Debug log----------------------------------------------------------------------
1629
1630 }
1631
1632 //!
1633 //! get private key file password (for callback function)
1634 //! @return password string
1635 std::string l7vs::virtualservice_tcp::get_ssl_password()
1636 {
1637     //*-------- DEBUG LOG --------*/
1638     if (unlikely(LOG_LV_DEBUG ==
1639                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1640         std::stringstream buf;
1641         buf << "in_function : ";
1642         buf << "std::string l7vs::virtualservice_tcp::get_ssl_password()";
1643         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 98, buf.str(),
1644                              __FILE__, __LINE__ );
1645     }
1646     //*------ DEBUG LOG END ------*/
1647
1648     // Get password from file.
1649     std::string retstr = "";
1650     FILE *fp;
1651     char buf[MAX_SSL_PASSWD_SIZE + 3];
1652     if ((fp = fopen((private_key_passwd_dir + private_key_passwd_file).c_str(),
1653                     "r")) == NULL) {
1654         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
1655                              "Password file cannot open.", __FILE__, __LINE__ );
1656     } else {
1657         if (fgets(buf, MAX_SSL_PASSWD_SIZE + 3, fp) == NULL) {
1658             Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
1659                                  "Password not found in file.",
1660                                  __FILE__, __LINE__ );
1661         } else {
1662             if ( strlen(buf) > MAX_SSL_PASSWD_SIZE ) {
1663                 Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
1664                                      "Password is too long.",
1665                                      __FILE__, __LINE__ );
1666             } else {
1667                 buf[strlen(buf) - 1] = '\0';
1668                 retstr = buf;
1669             }
1670         }
1671         fclose(fp);
1672     }
1673
1674     //*-------- DEBUG LOG --------*/
1675     if (unlikely(LOG_LV_DEBUG ==
1676                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1677         std::stringstream buf;
1678         buf << "out_function : ";
1679         buf << "std::string l7vs::virtualservice_tcp::get_ssl_password() : ";
1680         buf << "retstr = " << retstr;
1681         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 99, buf.str(),
1682                              __FILE__, __LINE__ );
1683     }
1684     //*------ DEBUG LOG END ------*/
1685
1686     return retstr;
1687 }
1688
1689 //!
1690 //! Convert verify option string to intger(#define).
1691 //!
1692 //! @param[in] opt_string  option string
1693 //! @retval    ret         option value
1694 //! @retval    -1          no match
1695 int l7vs::virtualservice_tcp::conv_verify_option(std::string opt_string)
1696 {
1697     //*-------- DEBUG LOG --------*/
1698     if (unlikely(LOG_LV_DEBUG ==
1699                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1700         std::stringstream buf;
1701         buf << "in_function : ";
1702         buf << "int virtualservice_tcp::conv_verify_option";
1703         buf << "(std::string opt_string) : ";
1704         buf << "opt_string = " << opt_string;
1705         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 100, buf.str(),
1706                              __FILE__, __LINE__ );
1707     }
1708     //*------ DEBUG LOG END ------*/
1709
1710     int ret = -1;
1711     //!
1712     // /usr/include/openssl/ssl.h
1713     // #define SSL_VERIFY_NONE                 0x00
1714     // #define SSL_VERIFY_PEER                 0x01
1715     // #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
1716     // #define SSL_VERIFY_CLIENT_ONCE          0x04
1717     //
1718     if (opt_string == "SSL_VERIFY_NONE") {
1719         ret = SSL_VERIFY_NONE;
1720     } else if (opt_string == "SSL_VERIFY_PEER") {
1721         ret = SSL_VERIFY_PEER;
1722     } else if (opt_string == "SSL_VERIFY_FAIL_IF_NO_PEER_CERT") {
1723         ret = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1724     } else if (opt_string == "SSL_VERIFY_CLIENT_ONCE") {
1725         ret = SSL_VERIFY_CLIENT_ONCE;
1726     } else {
1727         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
1728                              "verify option string no match.",
1729                              __FILE__, __LINE__ );
1730     }
1731
1732     //*-------- DEBUG LOG --------*/
1733     if (unlikely(LOG_LV_DEBUG ==
1734                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1735         std::stringstream buf;
1736         buf << "out_function : ";
1737         buf << "int virtualservice_tcp::conv_verify_option";
1738         buf << "(std::string opt_string) : ";
1739         buf << "return_value = " << ret;
1740         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 101, buf.str(),
1741                              __FILE__, __LINE__ );
1742     }
1743     //*------ DEBUG LOG END ------*/
1744     // if ret == -1 then No match.
1745     return ret;
1746 }
1747
1748 //!
1749 // Convert SSL option string to intger(#define).
1750 //
1751 // @param[in] opt_string  option string
1752 // @retval    ret         option value
1753 // @retval    -1          no match
1754 long int l7vs::virtualservice_tcp::conv_ssl_option(std::string opt_string)
1755 {
1756     //*-------- DEBUG LOG --------*/
1757     if (unlikely(LOG_LV_DEBUG ==
1758                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1759         std::stringstream buf;
1760         buf << "in_function : ";
1761         buf << "long int virtualservice_tcp::conv_ssl_option";
1762         buf << "(std::string opt_string) : ";
1763         buf << "opt_string = " << opt_string;
1764         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 102, buf.str(),
1765                              __FILE__, __LINE__ );
1766     }
1767     //*------ DEBUG LOG END ------*/
1768
1769     long int ret = -1;
1770     //!
1771     // /usr/include/openssl/ssl.h
1772     // #define SSL_OP_MICROSOFT_SESS_ID_BUG                    0x00000001L
1773     // #define SSL_OP_NETSCAPE_CHALLENGE_BUG                   0x00000002L
1774     // #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG         0x00000008L
1775     // #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG              0x00000010L
1776     // #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER               0x00000020L
1777     // #define SSL_OP_MSIE_SSLV2_RSA_PADDING                   0x00000040L
1778     // #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG                 0x00000080L
1779     // #define SSL_OP_TLS_D5_BUG                               0x00000100L
1780     // #define SSL_OP_TLS_BLOCK_PADDING_BUG                    0x00000200L
1781     // #define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS              0x00000800L
1782     // #define SSL_OP_ALL                                      0x00000FF7L
1783     // #define SSL_OP_NO_QUERY_MTU                             0x00001000L
1784     // #define SSL_OP_COOKIE_EXCHANGE                          0x00002000L
1785     // #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION   0x00010000L
1786     // #define SSL_OP_SINGLE_ECDH_USE                          0x00080000L
1787     // #define SSL_OP_SINGLE_DH_USE                            0x00100000L
1788     // #define SSL_OP_EPHEMERAL_RSA                            0x00200000L
1789     // #define SSL_OP_CIPHER_SERVER_PREFERENCE                 0x00400000L
1790     // #define SSL_OP_TLS_ROLLBACK_BUG                         0x00800000L
1791     // #define SSL_OP_NO_SSLv2                                 0x01000000L
1792     // #define SSL_OP_NO_SSLv3                                 0x02000000L
1793     // #define SSL_OP_NO_TLSv1                                 0x04000000L
1794     // #define SSL_OP_PKCS1_CHECK_1                            0x08000000L
1795     // #define SSL_OP_PKCS1_CHECK_2                            0x10000000L
1796     // #define SSL_OP_NETSCAPE_CA_DN_BUG                       0x20000000L
1797     // #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG          0x40000000L
1798     if (opt_string == "SSL_OP_MICROSOFT_SESS_ID_BUG") {
1799         ret = SSL_OP_MICROSOFT_SESS_ID_BUG;
1800     } else if (opt_string == "SSL_OP_NETSCAPE_CHALLENGE_BUG") {
1801         ret = SSL_OP_NETSCAPE_CHALLENGE_BUG;
1802     } else if (opt_string == "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG") {
1803         ret = SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
1804     } else if (opt_string == "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG") {
1805         ret = SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
1806     } else if (opt_string == "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER") {
1807         ret = SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
1808     } else if (opt_string == "SSL_OP_MSIE_SSLV2_RSA_PADDING") {
1809         ret = SSL_OP_MSIE_SSLV2_RSA_PADDING;
1810     } else if (opt_string == "SSL_OP_SSLEAY_080_CLIENT_DH_BUG") {
1811         ret = SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
1812     } else if (opt_string == "SSL_OP_TLS_D5_BUG") {
1813         ret = SSL_OP_TLS_D5_BUG;
1814     } else if (opt_string == "SSL_OP_TLS_BLOCK_PADDING_BUG") {
1815         ret = SSL_OP_TLS_BLOCK_PADDING_BUG;
1816     } else if (opt_string == "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS") {
1817         ret = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
1818     } else if (opt_string == "SSL_OP_ALL") {
1819         // boost::asio::ssl::context::default_workarounds
1820         ret = SSL_OP_ALL;
1821     } else if (opt_string == "SSL_OP_NO_QUERY_MTU") {
1822         ret = SSL_OP_NO_QUERY_MTU;
1823     } else if (opt_string == "SSL_OP_COOKIE_EXCHANGE") {
1824         ret = SSL_OP_COOKIE_EXCHANGE;
1825     } else if (opt_string == "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION") {
1826         ret = SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
1827     } else if (opt_string == "SSL_OP_SINGLE_ECDH_USE") {
1828         ret = SSL_OP_SINGLE_ECDH_USE;
1829     } else if (opt_string == "SSL_OP_SINGLE_DH_USE") {
1830         // boost::asio::ssl::context::single_dh_use
1831         ret = SSL_OP_SINGLE_DH_USE;
1832     } else if (opt_string == "SSL_OP_EPHEMERAL_RSA") {
1833         ret = SSL_OP_EPHEMERAL_RSA;
1834     } else if (opt_string == "SSL_OP_CIPHER_SERVER_PREFERENCE") {
1835         ret = SSL_OP_CIPHER_SERVER_PREFERENCE;
1836     } else if (opt_string == "SSL_OP_TLS_ROLLBACK_BUG") {
1837         ret = SSL_OP_TLS_ROLLBACK_BUG;
1838     } else if (opt_string == "SSL_OP_NO_SSLv2") {
1839         // boost::asio::ssl::context::no_sslv2
1840         ret = SSL_OP_NO_SSLv2;
1841     } else if (opt_string == "SSL_OP_NO_SSLv3") {
1842         // boost::asio::ssl::context::no_sslv3
1843         ret = SSL_OP_NO_SSLv3;
1844     } else if (opt_string == "SSL_OP_NO_TLSv1") {
1845         // boost::asio::ssl::context::no_tlsv1
1846         ret = SSL_OP_NO_TLSv1;
1847     } else if (opt_string == "SSL_OP_PKCS1_CHECK_1") {
1848         ret = SSL_OP_PKCS1_CHECK_1;
1849     } else if (opt_string == "SSL_OP_PKCS1_CHECK_2") {
1850         ret = SSL_OP_PKCS1_CHECK_2;
1851     } else if (opt_string == "SSL_OP_NETSCAPE_CA_DN_BUG") {
1852         ret = SSL_OP_NETSCAPE_CA_DN_BUG;
1853     } else if (opt_string == "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG") {
1854         ret = SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
1855     } else {
1856         Logger::putLogError( LOG_CAT_L7VSD_VIRTUALSERVICE, 23,
1857                              "ssl option string no match.",
1858                              __FILE__, __LINE__ );
1859     }
1860
1861     //*-------- DEBUG LOG --------*/
1862     if (unlikely(LOG_LV_DEBUG ==
1863                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1864         std::stringstream buf;
1865         buf << "out_function : ";
1866         buf << "long int virtualservice_tcp::conv_ssl_option";
1867         buf << "(std::string opt_string) : ";
1868         buf << "return_value = " << ret;
1869         Logger::putLogDebug( LOG_CAT_L7VSD_VIRTUALSERVICE, 103, buf.str(),
1870                              __FILE__, __LINE__ );
1871     }
1872     //------ DEBUG LOG END ------*/
1873     // if ret == -1 then No match.
1874     return ret;
1875 }
1876
1877 //!
1878 //! get ssl parameter
1879 //! @return get ssl parameter result
1880 bool l7vs::virtualservice_tcp::get_ssl_parameter()
1881 {
1882     //*-------- DEBUG LOG --------*/
1883     if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
1884         Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 104,
1885             "in_function : bool virtualservice_tcp::get_ssl_parameter()",
1886              __FILE__, __LINE__ );
1887     }
1888     //*------ DEBUG LOG END ------*/
1889     typedef std::vector< std::string > string_vector_type;
1890
1891     Parameter param;
1892     string_vector_type string_vector;
1893     l7vs::error_code err;
1894     bool retbool = false;
1895
1896     try {
1897         // param init ( ssl configuration file )
1898         if (unlikely(!param.init(l7vs::PARAM_COMP_SSL, ssl_file_name))) {
1899             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 24,
1900                                 "SSL config file read error.",
1901                                 __FILE__, __LINE__ );
1902             throw -1;
1903         }
1904
1905         //// SSL context parameter
1906         // Get parameter "ca_dir".
1907         ca_dir = param.get_string(l7vs::PARAM_COMP_SSL, "ca_dir",
1908                                   err, ssl_file_name);
1909         if (unlikely(err) || ca_dir == "") {
1910             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 9,
1911                                "ca_dir parameter not found. Use default value.",
1912                                __FILE__, __LINE__ );
1913             ca_dir = DEFAULT_SSL_CA_DIR;
1914         }
1915
1916         // Get parameter "ca_file".
1917         ca_file = param.get_string(l7vs::PARAM_COMP_SSL, "ca_file",
1918                                    err, ssl_file_name);
1919         if (unlikely(err)) {
1920             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 25,
1921                         "Cannot get ca_file parameter.",
1922                         __FILE__, __LINE__ );
1923             throw -1;
1924         }
1925
1926         // Get parameter "cert_chain_dir".
1927         cert_chain_dir = param.get_string(l7vs::PARAM_COMP_SSL,
1928                                           "cert_chain_dir",
1929                                           err,
1930                                           ssl_file_name);
1931         if (unlikely(err) || cert_chain_dir == "") {
1932             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 10,
1933                        "cert_chain_dir parameter not found. Use default value.",
1934                        __FILE__, __LINE__ );
1935             cert_chain_dir = DEFAULT_SSL_CERT_CHAIN_DIR;
1936         }
1937
1938         // Get parameter "cert_chain_file".
1939         cert_chain_file = param.get_string(l7vs::PARAM_COMP_SSL,
1940                                            "cert_chain_file",
1941                                            err,
1942                                            ssl_file_name);
1943         if (unlikely(err) || cert_chain_file == "") {
1944             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 26,
1945                         "Cannot get cert_chain_file parameter.",
1946                         __FILE__, __LINE__ );
1947             throw -1;
1948         }
1949
1950         // Get parameter "private_key_dir".
1951         private_key_dir = param.get_string(l7vs::PARAM_COMP_SSL,
1952                                            "private_key_dir",
1953                                            err,
1954                                            ssl_file_name);
1955         if (unlikely(err) || private_key_dir == "") {
1956             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 11,
1957                     "private_key_dir parameter not found. Use default value.",
1958                     __FILE__, __LINE__ );
1959             private_key_dir = DEFAULT_SSL_PRIVATE_KEY_DIR;
1960         }
1961
1962         // Get parameter "private_key_file".
1963         private_key_file = param.get_string(l7vs::PARAM_COMP_SSL,
1964                                             "private_key_file",
1965                                             err,
1966                                             ssl_file_name);
1967         if (unlikely(err) || private_key_file == "") {
1968             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 27,
1969                         "Cannot get private_key_file parameter.",
1970                         __FILE__, __LINE__ );
1971             throw -1;
1972         }
1973
1974         // Get parameter "private_key_filetype".
1975         // and convert string to filetype define value.
1976         //!
1977         // /usr/include/openssl/ssl.h
1978         // #define SSL_FILETYPE_PEM        X509_FILETYPE_PEM  ->1
1979         // #define SSL_FILETYPE_ASN1       X509_FILETYPE_ASN1 ->2
1980         //
1981
1982         std::string filetype_str = param.get_string(
1983                                        l7vs::PARAM_COMP_SSL,
1984                                        "private_key_filetype",
1985                                        err,
1986                                        ssl_file_name);
1987         if (unlikely(err) || filetype_str == "") {
1988             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 12,
1989                 "private_key_filetype parameter not found. Use default value.",
1990                 __FILE__, __LINE__ );
1991             private_key_filetype = DEFAULT_SSL_PRIVATE_KEY_FILETYPE;
1992         } else if (filetype_str == "SSL_FILETYPE_PEM") {
1993             private_key_filetype = boost::asio::ssl::context::pem;
1994         } else if (filetype_str == "SSL_FILETYPE_ASN1") {
1995             private_key_filetype = boost::asio::ssl::context::asn1;
1996         } else {
1997             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 28,
1998                         "private_key_filetype convert error.",
1999                         __FILE__, __LINE__ );
2000             throw -1;
2001         }
2002
2003         // Get parameter "private_key_passwd_dir".
2004         private_key_passwd_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2005                                                   "private_key_passwd_dir",
2006                                                   err,
2007                                                   ssl_file_name);
2008         if (unlikely(err) || private_key_passwd_dir == "") {
2009             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 13,
2010               "private_key_passwd_dir parameter not found. Use default value.",
2011               __FILE__, __LINE__ );
2012             private_key_passwd_dir = DEFAULT_SSL_PRIVATE_KEY_PASSWD_DIR;
2013         }
2014
2015         // Get parameter "private_key_passwd_file".
2016         private_key_passwd_file = param.get_string(l7vs::PARAM_COMP_SSL,
2017                                                    "private_key_passwd_file",
2018                                                    err,
2019                                                    ssl_file_name);
2020         if (unlikely(err) || private_key_passwd_file == "") {
2021             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 29,
2022                         "Cannot get private_key_passwd_file parameter.",
2023                         __FILE__, __LINE__ );
2024             throw -1;
2025         }
2026
2027         // Get parameter "verify_options".
2028         param.get_multistring(l7vs::PARAM_COMP_SSL,
2029                               "verify_options",
2030                               string_vector,
2031                               err,
2032                               ssl_file_name);
2033         if (unlikely(err)) {
2034             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 14,
2035                        "verify_options parameter not found. Use default value.",
2036                        __FILE__, __LINE__ );
2037             verify_options = DEFAULT_SSL_VERIFY_OPTIONS;
2038         } else {
2039             // Make verify option bit data.
2040             for (string_vector_type::iterator itr = string_vector.begin();
2041                  itr != string_vector.end(); ++itr) {
2042                 // Convert string to define value.
2043                 int int_val = conv_verify_option(*itr);
2044                 if (unlikely(int_val == -1)) {
2045                     Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 30,
2046                                 "verify_options convert error.",
2047                                 __FILE__, __LINE__ );
2048                     throw -1;
2049                 }
2050                 verify_options = (verify_options | int_val);
2051             }
2052         }
2053
2054         // Get parameter "verify_cert_depth".
2055         verify_cert_depth = param.get_int(l7vs::PARAM_COMP_SSL,
2056                                           "verify_cert_depth",
2057                                           err,
2058                                           ssl_file_name);
2059         if (unlikely(err)) {
2060             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 15,
2061                 "verify_cert_depth parameter not found. Use default value.",
2062                 __FILE__, __LINE__ );
2063             verify_cert_depth = DEFAULT_SSL_VERIFY_CERT_DEPTH;
2064         } else if (unlikely(verify_cert_depth < 0 ||
2065                    verify_cert_depth > INT_MAX)) {
2066             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 31,
2067                         "Invalid verify_cert_depth parameter value.",
2068                         __FILE__, __LINE__ );
2069             throw -1;
2070         }
2071
2072         // Get parameter "ssl_options".
2073         // and Check dh parameter file use or not.
2074         is_tmp_dh_use = false;
2075         param.get_multistring(l7vs::PARAM_COMP_SSL,
2076                               "ssl_options",
2077                               string_vector,
2078                               err,
2079                               ssl_file_name);
2080         if (unlikely(err)) {
2081             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 16,
2082                        "ssl_options parameter not found. Use default value.",
2083                        __FILE__, __LINE__ );
2084             ssl_options = DEFAULT_SSL_OPTIONS;
2085             is_tmp_dh_use = true;
2086         } else {
2087             // Make ssl option bit data.
2088             for (string_vector_type::iterator itr = string_vector.begin();
2089                  itr != string_vector.end(); ++itr) {
2090                 // Convert string to define value.
2091                 long int longint_val = conv_ssl_option(*itr);
2092                 if (unlikely(longint_val == -1)) {
2093                     Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 32,
2094                                 "ssl_options convert error.",
2095                                 __FILE__, __LINE__ );
2096                     throw -1;
2097                 } else if (longint_val == SSL_OP_SINGLE_DH_USE) {
2098                     is_tmp_dh_use = true;
2099                 }
2100                 ssl_options = (ssl_options | longint_val);
2101             }
2102         }
2103
2104         if (is_tmp_dh_use) {
2105             // Get parameter "tmp_dh_dir".
2106             tmp_dh_dir = param.get_string(l7vs::PARAM_COMP_SSL,
2107                                           "tmp_dh_dir",
2108                                           err,
2109                                           ssl_file_name);
2110             if (unlikely(err) || tmp_dh_dir == "") {
2111                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 17,
2112                            "tmp_dh_dir parameter not found. Use default value.",
2113                            __FILE__, __LINE__ );
2114                 tmp_dh_dir = DEFAULT_SSL_TMP_DH_DIR;
2115             }
2116             // Get parameter "tmp_dh_file".
2117             tmp_dh_file = param.get_string(l7vs::PARAM_COMP_SSL,
2118                                            "tmp_dh_file",
2119                                            err,
2120                                            ssl_file_name);
2121             if (unlikely(err) || tmp_dh_file == "") {
2122                 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 33,
2123                             "Cannot get tmp_dh_file parameter.",
2124                             __FILE__, __LINE__ );
2125                 throw -1;
2126             }
2127         }
2128
2129         // Get parameter "cipher_list".
2130         cipher_list = param.get_string(l7vs::PARAM_COMP_SSL,
2131                                        "cipher_list",
2132                                        err,
2133                                        ssl_file_name);
2134         if (unlikely(err) || cipher_list == "") {
2135             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 18,
2136                        "cipher_list parameter not found. Use default value.",
2137                        __FILE__, __LINE__ );
2138             cipher_list = DEFAULT_SSL_CIPHER_LIST;
2139         }
2140
2141         //// SSL session cache parameter
2142         // Get parameter "session_cache".
2143         is_session_cache_use = false;
2144         std::string cache_str = param.get_string(l7vs::PARAM_COMP_SSL,
2145                                                  "session_cache",
2146                                                  err,
2147                                                  ssl_file_name);
2148         if (unlikely(err) || cache_str == "") {
2149             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 19,
2150                        "session_cache parameter not found. Use default value.",
2151                        __FILE__, __LINE__ );
2152             is_session_cache_use = true;
2153         } else if (cache_str == "on") {
2154             is_session_cache_use = true;
2155         } else if (cache_str == "off") {
2156             is_session_cache_use = false;
2157         } else {
2158             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 34,
2159                         "Invalid session_cache parameter value.",
2160                         __FILE__, __LINE__ );
2161             throw -1;
2162         }
2163
2164         if (is_session_cache_use) {
2165             session_cache_mode = DEFAULT_SSL_SESSION_CACHE_MODE;
2166             // Get parameter "session_cache_size".
2167             session_cache_size = param.get_int(l7vs::PARAM_COMP_SSL,
2168                                                "session_cache_size",
2169                                                err,
2170                                                ssl_file_name);
2171             if (unlikely(err)) {
2172                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 20,
2173                   "session_cache_size parameter not found. Use default value.",
2174                   __FILE__, __LINE__ );
2175                 session_cache_size = DEFAULT_SSL_SESSION_CACHE_SIZE;
2176             } else if (session_cache_size < 0 ||
2177                        session_cache_size > INT_MAX) {
2178                 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 35,
2179                             "Invalid session_cache_size parameter value.",
2180                             __FILE__, __LINE__ );
2181                 throw -1;
2182             }
2183             // Get parameter "session_cache_timeout".
2184             session_cache_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2185                                                   "session_cache_timeout",
2186                                                   err,
2187                                                   ssl_file_name);
2188             if (unlikely(err)) {
2189                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 21,
2190                 "session_cache_timeout parameter not found. Use default value.",
2191                 __FILE__, __LINE__ );
2192                 session_cache_timeout = DEFAULT_SSL_SESSION_CACHE_TIMEOUT;
2193             } else if (session_cache_timeout < 0 ||
2194                        session_cache_timeout > INT_MAX) {
2195                 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 36,
2196                             "Invalid session_cache_timeout parameter value.",
2197                             __FILE__, __LINE__ );
2198                 throw -1;
2199             }
2200         } else {
2201             session_cache_mode = SSL_SESS_CACHE_OFF;
2202         }
2203
2204         //// SSL handshake timer parameter
2205         // Get parameter "timeout_sec".
2206         handshake_timeout = param.get_int(l7vs::PARAM_COMP_SSL,
2207                                           "timeout_sec",
2208                                           err,
2209                                           ssl_file_name);
2210         if (unlikely(err)) {
2211             Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 22,
2212                        "timeout_sec parameter not found. Use default value.",
2213                        __FILE__, __LINE__ );
2214             handshake_timeout = DEFAULT_SSL_HANDSHAKE_TIMEOUT;
2215         } else if (handshake_timeout <= 0 || handshake_timeout > INT_MAX) {
2216             Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 37,
2217                         "Invalid timeout_sec parameter value.",
2218                         __FILE__, __LINE__ );
2219             throw -1;
2220         }
2221
2222         retbool = true;
2223
2224     } catch (int e) {
2225         retbool = false;
2226     }
2227
2228     //*-------- DEBUG LOG --------*/
2229     if (unlikely(LOG_LV_DEBUG ==
2230                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2231         std::stringstream buf;
2232         buf<<"out_function : bool virtualservice_tcp::get_ssl_parameter() : ";
2233         buf<<"ca_dir = "                 << ca_dir                  << ", ";
2234         buf<<"ca_file = "                << ca_file                 << ", ";
2235         buf<<"cert_chain_dir = "         << cert_chain_dir          << ", ";
2236         buf<<"cert_chain_file = "        << cert_chain_file         << ", ";
2237         buf<<"private_key_dir = "        << private_key_dir         << ", ";
2238         buf<<"private_key_file = "       << private_key_file        << ", ";
2239         buf<<"private_key_filetype = "   << private_key_filetype    << ", ";
2240         buf<<"private_key_passwd_dir = " << private_key_passwd_dir  << ", ";
2241         buf<<"private_key_passwd_file = "<< private_key_passwd_file << ", ";
2242         buf<<"verify_options = "         << verify_options          << ", ";
2243         buf<<"verify_cert_depth = "      << verify_cert_depth       << ", ";
2244         buf<<"ssl_options = "            << ssl_options             << ", ";
2245         if (is_tmp_dh_use) {
2246             buf<< "tmp_dh_dir = "        << tmp_dh_dir              << ", ";
2247             buf<< "tmp_dh_file = "       << tmp_dh_file             << ", ";
2248         }
2249         buf<<"cipher_list = "            << cipher_list             << ", ";
2250         buf<<"session_cache_mode = "     << session_cache_mode      << ", ";
2251         if (is_session_cache_use) {
2252             buf<<"session_cache_size = " << session_cache_size      << ", ";
2253             buf<<"session_cache_timeout = "<< session_cache_timeout << ", ";
2254         }
2255         buf<<"handshake_timeout = "      << handshake_timeout;
2256         Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 105,
2257                             buf.str(),
2258                             __FILE__, __LINE__ );
2259     }
2260     //*------ DEBUG LOG END ------*/
2261     return retbool;
2262 }
2263
2264 //!
2265 // set ssl context and ssl session cache configuration
2266 // @return set ssl config result
2267 bool l7vs::virtualservice_tcp::set_ssl_config()
2268 {
2269     //*-------- DEBUG LOG --------*/
2270     if (unlikely(LOG_LV_DEBUG ==
2271                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2272         Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 106,
2273                     "in_function : bool virtualservice_tcp::set_ssl_config()",
2274                     __FILE__, __LINE__ );
2275     }
2276     //*------ DEBUG LOG END ------*/
2277
2278     bool retbool = false;
2279
2280     try {
2281         //// SSL context setting.
2282         // Set root CA.
2283         if (ca_file.size() == 0) {
2284             // specified CA path.
2285             try {
2286                 sslcontext.add_verify_path(ca_dir);
2287             } catch (std::exception& e) {
2288                 std::stringstream buf;
2289                 buf << "Set root CA path error : " << e.what() << ".";
2290                 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 107,
2291                             buf.str(),
2292                             __FILE__, __LINE__ );
2293                 throw -1;
2294             }
2295         } else {
2296             // specified CA file.
2297             try {
2298                 sslcontext.load_verify_file(ca_dir + ca_file);
2299             } catch (std::exception& e) {
2300                 std::stringstream buf;
2301                 buf << "Set root CA file error : " << e.what() << ".";
2302                 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 108,
2303                             buf.str(),
2304                             __FILE__, __LINE__ );
2305                 throw -1;
2306             }
2307         }
2308
2309         // Set certificate chain file.
2310         try {
2311             sslcontext.use_certificate_chain_file(
2312                                              cert_chain_dir + cert_chain_file);
2313         } catch (std::exception& e) {
2314             std::stringstream buf;
2315             buf << "Set certificate chain file error : " << e.what() << ".";
2316             Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 109, buf.str(),
2317                                 __FILE__, __LINE__ );
2318             throw -1;
2319         }
2320
2321         // Set password callback function.
2322         try {
2323             sslcontext.set_password_callback(
2324                     boost::bind(&virtualservice_tcp::get_ssl_password, this));
2325         } catch (std::exception& e) {
2326             std::stringstream buf;
2327             buf << "Set password callback error : " << e.what() << ".";
2328             Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 110, buf.str(),
2329                                 __FILE__, __LINE__ );
2330             throw -1;
2331         }
2332
2333         // Set private key file and filetype.
2334         try {
2335             sslcontext.use_private_key_file(
2336                     private_key_dir + private_key_file, private_key_filetype);
2337         } catch (std::exception& e) {
2338             std::stringstream buf;
2339             buf <<"Set private key file and filetype error : "<<e.what()<<".";
2340             Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 111, buf.str(),
2341                                 __FILE__, __LINE__ );
2342             throw -1;
2343         }
2344
2345         // Set verify options on the context.
2346         try {
2347             sslcontext.set_verify_mode(verify_options);
2348         } catch (std::exception& e) {
2349             std::stringstream buf;
2350             buf << "Set verify option error : " << e.what() << ".";
2351             Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 112, buf.str(),
2352                                 __FILE__, __LINE__ );
2353             throw -1;
2354         }
2355
2356         // Set verify depth on the context.
2357         SSL_CTX_set_verify_depth(sslcontext.impl(), verify_cert_depth);
2358
2359         // Set SSL options on the context.
2360         try {
2361             sslcontext.set_options(ssl_options);
2362         } catch (std::exception& e) {
2363             std::stringstream buf;
2364             buf << "Set SSL option error : " << e.what() << ".";
2365             Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 113, buf.str(),
2366                                 __FILE__, __LINE__ );
2367             throw -1;
2368         }
2369
2370         // Set temporary Diffie-Hellman parameters file.
2371         if (is_tmp_dh_use) {
2372             try {
2373                 sslcontext.use_tmp_dh_file(tmp_dh_dir + tmp_dh_file);
2374             } catch (std::exception& e) {
2375                 std::stringstream buf;
2376                 buf << "Set tmp DH file error : " << e.what() << ".";
2377                 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 114,
2378                             buf.str(),
2379                             __FILE__, __LINE__ );
2380                 throw -1;
2381             }
2382
2383         }
2384
2385         // Set cipher list on the context.
2386         if (unlikely(SSL_CTX_set_cipher_list(sslcontext.impl(),
2387                                              cipher_list.c_str()) != 1)) {
2388             std::stringstream buf;
2389             buf << "Set cipher list error.";
2390             Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 115,
2391                         buf.str(),
2392                         __FILE__, __LINE__ );
2393             throw -1;
2394         }
2395
2396         //// SSL session cache setting.
2397         if (is_session_cache_use) {
2398             // Set session id context on the context.
2399             if (unlikely( SSL_CTX_set_session_id_context(
2400                               sslcontext.impl(),
2401                               (const unsigned char *)"ultramonkey", 11) != 1)) {
2402                 std::stringstream buf;
2403                 buf << "Set session id context error.";
2404                 Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 116,
2405                             buf.str(),
2406                             __FILE__, __LINE__ );
2407                 throw -1;
2408             }
2409
2410             // Set session cache mode on the context.
2411             SSL_CTX_set_session_cache_mode(
2412                                         sslcontext.impl(),session_cache_mode);
2413
2414             // Set session cache size on the context.
2415             SSL_CTX_sess_set_cache_size(sslcontext.impl(), session_cache_size);
2416
2417             // Set session cache timeout on the context.
2418             SSL_CTX_set_timeout(sslcontext.impl(), session_cache_timeout);
2419
2420         } else {
2421             // session cache OFF.
2422             SSL_CTX_set_session_cache_mode(sslcontext.impl(),
2423                                            SSL_SESS_CACHE_OFF);
2424         }
2425
2426         retbool = true;
2427
2428     } catch (int e) {
2429         retbool = false;
2430     }
2431     //*-------- DEBUG LOG --------*/
2432     if (unlikely(LOG_LV_DEBUG ==
2433                  Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
2434         std::stringstream buf;
2435         buf << "out_function : bool virtualservice_tcp::set_ssl_config() : ";
2436         get_ssl_config(buf);
2437         Logger::putLogDebug(LOG_CAT_L7VSD_VIRTUALSERVICE, 117, buf.str(),
2438                             __FILE__, __LINE__ );
2439     }
2440     //*------ DEBUG LOG END ------*/
2441     return retbool;
2442 }
2443
2444 //!
2445 // flush ssl session
2446 void l7vs::virtualservice_tcp::flush_ssl_session()
2447 {
2448     // check expired cached sessions and do flushing
2449     // Need ssl_context lock?
2450     SSL_CTX_flush_sessions(sslcontext.impl(), time(0));
2451 }
2452
2453 //!
2454 // get ssl configuration form ssl context. (for debug)
2455 void l7vs::virtualservice_tcp::get_ssl_config(std::stringstream& buf)
2456 {
2457     buf<<"SSL configuration information : ";
2458     buf<<"Verify mode[" << SSL_CTX_get_verify_mode(sslcontext.impl()) << "] ";
2459     buf<<"Verify depth["<< SSL_CTX_get_verify_depth(sslcontext.impl())<< "] ";
2460     buf<<"SSL options[" << SSL_CTX_get_options(sslcontext.impl()) << "] ";
2461     buf<<"Cache mode["  << SSL_CTX_get_session_cache_mode(sslcontext.impl());
2462     buf<<"] ";
2463     buf<<"Cache size["<<SSL_CTX_sess_get_cache_size(sslcontext.impl())<< "] ";
2464     buf<<"Cache timeout[" << SSL_CTX_get_timeout(sslcontext.impl()) << "] ";
2465 }
2466
2467 //!
2468 // get ssl session cache information form ssl context. (for debug)
2469 void l7vs::virtualservice_tcp::get_ssl_session_cache_info(std::stringstream& buf)
2470 {
2471     buf << "SSL session cache information : ";
2472     buf << "Session number[" << SSL_CTX_sess_number(sslcontext.impl())  << "] ";
2473     buf << "Accept["         << SSL_CTX_sess_accept(sslcontext.impl())  << "] ";
2474     buf << "Accept good["    << SSL_CTX_sess_accept_good(sslcontext.impl())  << "] ";
2475     buf << "Accept renegotiate[" << SSL_CTX_sess_accept_renegotiate(sslcontext.impl()) << "] ";
2476     buf << "Hits["  << SSL_CTX_sess_hits(sslcontext.impl())  << "] ";
2477     buf << "Misses["  << SSL_CTX_sess_misses(sslcontext.impl())  << "] ";
2478     buf << "Timeouts["  << SSL_CTX_sess_timeouts(sslcontext.impl())  << "] ";
2479     buf << "Cache full["  << SSL_CTX_sess_cache_full(sslcontext.impl())  << "] ";
2480 }
2481