OSDN Git Service

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