OSDN Git Service

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