OSDN Git Service

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