OSDN Git Service

Get ready for v3.0.3 release.
[ultramonkey-l7/ultramonkey-l7-v3.git] / l7vsd / src / tcp_ssl_socket.cpp
1 /*!
2  *    @file    tcp_ssl_socket.cpp
3  *    @brief    tcp ssl session socket class
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 <boost/thread/thread.hpp>
26
27 #include "tcp_ssl_socket.h"
28
29 namespace l7vs
30 {
31
32 //! handshake socket
33 //! @param[in]        handshake_type is handshaking as a server or client
34 //! @return           true is handshake success
35 //! @return           false is handshake failure
36 bool tcp_ssl_socket::handshake(boost::system::error_code &ec)
37 {
38         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
39                              LOG_CAT_L7VSD_SESSION))) {
40                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 74,
41                                     "in_function : tcp_ssl_socket::handshake",
42                                     __FILE__, __LINE__);
43         }
44
45         rw_scoped_lock scope_lock(close_mutex);
46
47         bool bres = false;
48         my_socket->handshake(boost::asio::ssl::stream_base::server, ec);
49         if (!ec) {
50                 bres = true;
51         } else if (ec != boost::asio::error::try_again) {
52                 handshake_error_flag = true;
53         }
54
55         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
56                              LOG_CAT_L7VSD_SESSION))) {
57                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 78,
58                                     "out_function : tcp_ssl_socket::handshake",
59                                     __FILE__, __LINE__);
60         }
61         return bres;
62 }
63
64 //! accept socket
65 void tcp_ssl_socket::accept()
66 {
67         rw_scoped_lock scope_lock(close_mutex);
68
69         open_flag = true;
70         //----Debug log--------------------------------------------------------
71         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
72                              LOG_CAT_L7VSD_SESSION))) {
73                 boost::system::error_code ec;
74                 std::stringstream buf;
75                 buf << "Thread ID[";
76                 buf << boost::this_thread::get_id();
77                 buf << "] tcp_ssl_socket::accept [";
78                 buf << my_socket->lowest_layer().remote_endpoint(ec);
79                 buf << "]";
80                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 54, buf.str(),
81                                     __FILE__, __LINE__);
82         }
83         //----Debug log--------------------------------------------------------
84
85         //set TCP_NODELAY
86         if (opt_info.nodelay_opt) {
87                 boost::system::error_code ec;
88                 boost::asio::ip::tcp::no_delay set_option(opt_info.nodelay_val);
89                 my_socket->lowest_layer().set_option(set_option, ec);
90                 if (unlikely(ec)) {
91                         //ERROR
92                         Logger::putLogError(LOG_CAT_L7VSD_SESSION, 107,
93                                             "socket option(TCP_NODELAY) set failed" ,
94                                             __FILE__, __LINE__);
95                 }
96         }
97
98         //set TCP_CORK
99         if (opt_info.cork_opt) {
100                 boost::system::error_code ec;
101                 int val = opt_info.cork_val;
102                 size_t len = sizeof(val);
103                 int err = ::setsockopt(my_socket->lowest_layer().native(), IPPROTO_TCP,
104                                        TCP_CORK, &val, len);
105                 if (unlikely(err)) {
106                         //ERROR
107                         Logger::putLogError(LOG_CAT_L7VSD_SESSION, 108,
108                                             "socket option(TCP_CORK) set failed" ,
109                                             __FILE__, __LINE__);
110                 }
111         }
112 }
113
114 //! close socket
115 //! @param[out]       ec is reference error code object
116 //! @return           true is socket close
117 //! @return           false is not open socket
118 bool tcp_ssl_socket::close(boost::system::error_code &ec)
119 {
120         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
121                              LOG_CAT_L7VSD_SESSION))) {
122                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 56,
123                                     "in_function : tcp_ssl_socket::close", __FILE__, __LINE__);
124         }
125
126         rw_scoped_lock scope_lock(close_mutex);
127
128         //----Debug log--------------------------------------------------------
129         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
130                              LOG_CAT_L7VSD_SESSION))) {
131                 if (open_flag) {
132                         boost::system::error_code ec;
133                         std::stringstream buf;
134                         buf << "Thread ID[";
135                         buf << boost::this_thread::get_id();
136                         buf << "] tcp_ssl_socket::close [";
137                         buf << my_socket->lowest_layer().remote_endpoint(ec);
138                         buf << "]";
139                         Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 58, buf.str(),
140                                             __FILE__, __LINE__);
141                 }
142         }
143         //----Debug log--------------------------------------------------------
144         bool bres = false;
145         if (likely(open_flag)) {
146                 open_flag = false;
147                 bres = true;
148         }
149         my_socket->shutdown(ec);
150         my_socket->lowest_layer().close(ec);
151
152         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
153                              LOG_CAT_L7VSD_SESSION))) {
154                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 57,
155                                     "out_function : tcp_ssl_socket::close", __FILE__, __LINE__);
156         }
157         return bres;
158 }
159
160 //! set non blocking mode of the socket
161 //! @param[out]     ec is reference error code object
162 //! @return         true is set non blocking mode
163 //! @return         false is set non blocking mode failure
164 bool tcp_ssl_socket::set_non_blocking_mode(boost::system::error_code &ec)
165 {
166         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
167                              LOG_CAT_L7VSD_SESSION))) {
168                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 60,
169                                     "in_function : tcp_ssl_socket::set_non_blocking_mode",
170                                     __FILE__, __LINE__);
171         }
172
173         rd_scoped_lock scope_lock(close_mutex);
174         bool bres = false;
175         boost::asio::socket_base::non_blocking_io cmd(true);
176         my_socket->lowest_layer().io_control(cmd, ec);
177         if (likely(!ec)) {
178                 // OK
179                 bres = true;
180                 non_blocking_flag = true;
181         }
182
183         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
184                              LOG_CAT_L7VSD_SESSION))) {
185                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 61,
186                                     "out_function : tcp_ssl_socket::set_non_blocking_mode",
187                                     __FILE__, __LINE__);
188         }
189         return bres;
190 }
191
192 //! write socket
193 //! @param[in]         buffers is write data buffer
194 //! @param[out]        ec is reference error code object
195 //! @return            write data size
196 std::size_t tcp_ssl_socket::write_some(
197         boost::asio::mutable_buffers_1 buffers,
198         boost::system::error_code &ec)
199 {
200         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
201                              LOG_CAT_L7VSD_SESSION))) {
202                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 63,
203                                     "in_function : tcp_ssl_socket::write_some",
204                                     __FILE__, __LINE__);
205         }
206
207         rw_scoped_lock scope_lock(close_mutex);
208         std::size_t res_size = 0;
209         if (likely(non_blocking_flag)) {
210                 res_size = my_socket->write_some(buffers, ec);
211                 if (unlikely(ec)) {
212                         if (likely(!open_flag)) {
213                                 res_size = 0;
214                                 ec.clear();
215                         }
216                 }
217         }
218         if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(
219                              LOG_CAT_L7VSD_SESSION))) {
220                 Logger::putLogDebug(LOG_CAT_L7VSD_SESSION, 64,
221                                     "out_function : tcp_ssl_socket::write_some",
222                                     __FILE__, __LINE__);
223         }
224         return res_size;
225 }
226
227 //! read socket
228 //! @param[out]        buffers is read data buffer
229 //! @param[out]        ec is reference error code object
230 //! @return            read data size
231 std::size_t tcp_ssl_socket::read_some(
232         boost::asio::mutable_buffers_1 buffers,
233         boost::system::error_code &ec)
234 {
235
236         rw_scoped_lock scope_lock(close_mutex);
237         std::size_t res_size = 0;
238         if (unlikely(open_flag && non_blocking_flag)) {
239                 //set TCP_QUICKACK
240                 if (opt_info.quickack_opt) {
241                         int val = opt_info.quickack_val;
242                         std::size_t len = sizeof(val);
243                         int err = ::setsockopt(my_socket->lowest_layer().native(), IPPROTO_TCP,
244                                                TCP_QUICKACK, &val, len);
245                         if (unlikely(err)) {
246                                 //ERROR
247                                 std::stringstream buf;
248                                 buf << "Thread ID[";
249                                 buf << boost::this_thread::get_id();
250                                 buf << "] socket option(TCP_QUICKACK) set failed : ";
251                                 buf << ec.message();
252                                 Logger::putLogError(LOG_CAT_L7VSD_SESSION, 109,
253                                                     buf.str() , __FILE__, __LINE__);
254                         }
255                 }
256                 boost::this_thread::yield();
257                 res_size = my_socket->read_some(buffers, ec);
258         }
259         return res_size;
260 }
261
262 }// namespace l7vs
263