OSDN Git Service

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