OSDN Git Service

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