UltraMonkey-L7 V3(multi-thread implementation)
リビジョン | a8e661bfc9c21b14db6f5b873ff60c8276c9bfbd (tree) |
---|---|
日時 | 2012-09-10 12:08:13 |
作者 | hibari <l05102@shib...> |
コミッター | hibari |
Edit spec file for generate devel package. And add module sample files.
@@ -57,6 +57,7 @@ else | ||
57 | 57 | AC_SUBST( libdir, [/usr/lib] ) |
58 | 58 | AC_SUBST( CXXFLAGS, -march=i686 ) |
59 | 59 | fi |
60 | +AC_SUBST( includedir, [/usr/include] ) | |
60 | 61 | |
61 | 62 | AC_ARG_WITH( |
62 | 63 | l7vs-moddir, |
@@ -67,6 +68,16 @@ AC_ARG_WITH( | ||
67 | 68 | ) |
68 | 69 | |
69 | 70 | AC_ARG_WITH( |
71 | + l7vs-includedir, | |
72 | + [ --with-l7vs-includedir=DIR l7vs headerfile is to be installed in DIR. | |
73 | + | |
74 | + [default=INCLUDEDIR/l7vs] | |
75 | +], | |
76 | + [ l7vs_includedir="$withval" ], | |
77 | + [ l7vs_includedir="${includedir}/l7vs" ] | |
78 | +) | |
79 | + | |
80 | +AC_ARG_WITH( | |
70 | 81 | l7vsadm-sockdir, |
71 | 82 | [ --with-l7vsadm-sockdir=DIR l7vsadm sockfile PATH. |
72 | 83 | [default=/var/run/l7vs] ], |
@@ -94,6 +105,7 @@ AC_SUBST(CC,g++) | ||
94 | 105 | AC_SUBST(exec_prefix, [/usr] ) |
95 | 106 | AC_SUBST(l7vsadm_sockdir) |
96 | 107 | AC_SUBST(l7vs_moddir) |
108 | +AC_SUBST(l7vs_includedir) | |
97 | 109 | AC_SUBST(l7vs_max_buffer_size) |
98 | 110 | AC_SUBST(l7vs_config) |
99 | 111 | AC_SUBST(MANDIR) |
@@ -0,0 +1,24 @@ | ||
1 | +AUTOMAKE_OPTIONS = foreign | |
2 | +L7VS_MODDIR = @l7vs_moddir@ | |
3 | +L7VS_INCLUDEDIR = @l7vs_includedir@ | |
4 | +MAX_BUFFER_SIZE = @l7vs_max_buffer_size@ | |
5 | + | |
6 | +AM_CPPFLAGS = \ | |
7 | + -g -O2 -fno-strict-aliasing -Wall -Werror -fPIC -pthread \ | |
8 | + -I$(L7VS_INCLUDEDIR) \ | |
9 | + -DMAX_BUFFER_SIZE=$(MAX_BUFFER_SIZE) | |
10 | + | |
11 | +lib_LTLIBRARIES = \ | |
12 | + libprotomod_simple.la | |
13 | + | |
14 | +libprotomod_simple_la_SOURCES = \ | |
15 | + protocol_module_base.h \ | |
16 | + http_protocol_module_base.h \ | |
17 | + http_protocol_module_base.cpp \ | |
18 | + protocol_module_simple.cpp | |
19 | + | |
20 | +install: | |
21 | + cp ./.libs/libprotomod_simple.so ./.libs/protomod_simple.so && \ | |
22 | + $(INSTALL) -m 755 -d $(L7VS_MODDIR) | |
23 | + $(INSTALL) -m 755 -D \ | |
24 | + ./.libs/protomod_simple.so $(L7VS_MODDIR) |
@@ -0,0 +1,25 @@ | ||
1 | +Sample source of protocol module for UltraMonkey-L7 . | |
2 | + | |
3 | +== Files == | |
4 | +./protocol | |
5 | +Makefile.am | |
6 | +configure.in | |
7 | +http_protocol_module_base.cpp | |
8 | +http_protocol_module_base.h | |
9 | +protocol_module_simple.cpp | |
10 | +protocol_module_simple.h | |
11 | + | |
12 | +== Set up == | |
13 | +*please install um-l7 devel package before compile. | |
14 | + | |
15 | +cp -r ./protocol /path/to/develop | |
16 | +cd /path/to/develop/protocol | |
17 | +autoreconf -ifv | |
18 | +./configure | |
19 | +make | |
20 | +make install | |
21 | + | |
22 | +== How to use this module == | |
23 | +l7vsadm -A -t IP:PORT -m simple | |
24 | + | |
25 | + |
@@ -0,0 +1,89 @@ | ||
1 | +AC_PREREQ(2.59) | |
2 | +AC_INIT(l7vsd) | |
3 | +PACKAGENAME=ultramonkeyl7-mod-simple-1.0.0 | |
4 | +VERSION=1.0.0 | |
5 | + | |
6 | +AM_INIT_AUTOMAKE($PACKAGENAME, $VERSION, no-define ) | |
7 | +AC_CONFIG_SRCDIR([config.h.in]) | |
8 | +AC_CONFIG_HEADER([config.h]) | |
9 | + | |
10 | +# Checks for programs. | |
11 | +AC_PROG_CXX | |
12 | +AC_PROG_LIBTOOL | |
13 | +AC_PROG_CPP | |
14 | +AC_PROG_INSTALL | |
15 | +AC_PROG_LN_S | |
16 | +AC_PROG_MAKE_SET | |
17 | + | |
18 | +# Checks for libraries. | |
19 | +AC_CHECK_LIB(dl, dlopen) | |
20 | +AC_CHECK_LIB(log4cxx, main, :, | |
21 | + [AC_MSG_ERROR( l7vsd require log4cxx library. )] ) | |
22 | +AC_CHECK_LIB(rt, main, :, | |
23 | + [AC_MSG_ERROR( l7vsd require rt library. )] ) | |
24 | +AC_CHECK_LIB(boost_thread-mt, main, :, | |
25 | + [AC_MSG_ERROR( l7vsd require boost library. )] ) | |
26 | +AC_CHECK_LIB(boost_system-mt, main, :, | |
27 | + [AC_MSG_ERROR( l7vsd require boost library. )] ) | |
28 | + | |
29 | +# Checks for header files. | |
30 | +AC_CHECK_HEADERS([limits.h unistd.h]) | |
31 | + | |
32 | +# Checks for typedefs, structures, and compiler characteristics. | |
33 | +AC_HEADER_STDBOOL | |
34 | +AC_C_CONST | |
35 | +AC_C_INLINE | |
36 | +AC_TYPE_SIZE_T | |
37 | +AC_STRUCT_TM | |
38 | + | |
39 | +# Checks for library functions. | |
40 | +AC_HEADER_STDC | |
41 | +AC_FUNC_MKTIME | |
42 | +AC_FUNC_STRFTIME | |
43 | +AC_CHECK_FUNCS([gethostname localtime_r memset]) | |
44 | + | |
45 | +# application-specific option | |
46 | +if test `uname -m` == "x86_64"; then | |
47 | + AC_SUBST( libdir, [/usr/lib64] ) | |
48 | +else | |
49 | + AC_SUBST( libdir, [/usr/lib] ) | |
50 | + AC_SUBST( CXXFLAGS, -march=i686 ) | |
51 | +fi | |
52 | +AC_SUBST( includedir, [/usr/include] ) | |
53 | + | |
54 | +AC_ARG_WITH( | |
55 | + l7vs-moddir, | |
56 | + [ --with-l7vs-moddir=DIR l7vs module is to be installed in DIR. | |
57 | + [default=LIBDIR/l7vs] ], | |
58 | + [ l7vs_moddir="$withval" ], | |
59 | + [ l7vs_moddir="${libdir}/l7vs" ] | |
60 | +) | |
61 | + | |
62 | +AC_ARG_WITH( | |
63 | + l7vs-includedir, | |
64 | + [ --with-l7vs-includedir=DIR l7vs headerfile is to be installed in DIR. | |
65 | + [default=INCLUDEDIR/l7vs] ], | |
66 | + [ l7vs_includedir="$withval" ], | |
67 | + [ l7vs_includedir="${includedir}/l7vs" ] | |
68 | +) | |
69 | + | |
70 | +AC_ARG_WITH( | |
71 | + l7vs-buffer-size, | |
72 | + [ --with-l7vs-buffer-size=NUM l7vsd using heap buffer size. | |
73 | + [default=4096] ], | |
74 | + [ l7vs_max_buffer_size="$withval" ], | |
75 | + [ l7vs_max_buffer_size=4096 ] | |
76 | +) | |
77 | + | |
78 | + | |
79 | +AC_SUBST(CC,g++) | |
80 | +AC_SUBST(exec_prefix, [/usr] ) | |
81 | +AC_SUBST(l7vs_moddir) | |
82 | +AC_SUBST(l7vs_includedir) | |
83 | +AC_SUBST(l7vs_max_buffer_size) | |
84 | +AC_SUBST(MANDIR) | |
85 | +AC_SUBST(ultramonkeyl7_version,ultramonkeyl7-$VERSION) | |
86 | + | |
87 | +AC_CONFIG_FILES([Makefile]) | |
88 | + | |
89 | +AC_OUTPUT |
@@ -0,0 +1,1296 @@ | ||
1 | +/* | |
2 | + * @file http_protocol_module_base.cpp | |
3 | + * @brief shared object http protocol module abstract 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 | +#include <boost/xpressive/xpressive.hpp> | |
25 | + | |
26 | +#include "http_protocol_module_base.h" | |
27 | +#include "utility.h" | |
28 | + | |
29 | +using namespace boost::xpressive; | |
30 | + | |
31 | +cregex method_regex | |
32 | += (as_xpr("GET") | as_xpr("HEAD") | as_xpr("POST") | | |
33 | + as_xpr("PUT") | as_xpr("PROPFIND") | as_xpr("PROPPATCH") | | |
34 | + as_xpr("OPTIONS") | as_xpr("CONNECT") | as_xpr("COPY") | | |
35 | + as_xpr("TRACE") | as_xpr("DELETE") | as_xpr("LOCK") | | |
36 | + as_xpr("UNLOCK") | as_xpr("MOVE") | as_xpr("MKCOL")) >> _s >> | |
37 | + +~_s >> _s >> | |
38 | + "HTTP/" >> _d >> "." >> _d; | |
39 | + | |
40 | +cregex version_regex_request | |
41 | += +alpha >> _s >> | |
42 | + +~_s >> _s >> | |
43 | + "HTTP/" >> (as_xpr("1.0") | as_xpr("1.1")); | |
44 | + | |
45 | +cregex version_regex_response | |
46 | += "HTTP/" >> (as_xpr("1.0") | as_xpr("1.1")) >> _s >> | |
47 | + repeat<3>(_d) >> _s >> | |
48 | + *_; | |
49 | + | |
50 | +cregex status_code_regex_check | |
51 | += "HTTP/" >> _d >> "." >> _d >> _s >> | |
52 | + range('1', '3') >> repeat<2>(_d) >> _s >> | |
53 | + *_; | |
54 | + | |
55 | +cregex method_and_version_regex | |
56 | += (as_xpr("GET") | as_xpr("HEAD") | as_xpr("POST") | | |
57 | + as_xpr("PUT") | as_xpr("PROPFIND") | as_xpr("PROPPATCH") | | |
58 | + as_xpr("OPTIONS") | as_xpr("CONNECT") | as_xpr("COPY") | | |
59 | + as_xpr("TRACE") | as_xpr("DELETE") | as_xpr("LOCK") | | |
60 | + as_xpr("UNLOCK") | as_xpr("MOVE") | as_xpr("MKCOL")) >> _s >> | |
61 | + +~_s >> _s >> | |
62 | + "HTTP/" >> (as_xpr("1.0") | as_xpr("1.1")); | |
63 | + | |
64 | +cregex version_and_status_code_regex | |
65 | += "HTTP/" >> (as_xpr("1.0") | as_xpr("1.1")) >> _s >> | |
66 | + range('1', '3') >> repeat<2>(_d) >> _s >> | |
67 | + *_; | |
68 | + | |
69 | +cregex uri_regex | |
70 | += +alpha >> _s >> | |
71 | + (s1 = *~_s) >> _s >> | |
72 | + "HTTP/" >> _d >> "." >> _d; | |
73 | + | |
74 | +cregex status_code_regex_find | |
75 | += "HTTP/" >> _d >> "." >> _d >> _s >> | |
76 | + (s1 = repeat<3>(_d)) >> _s >> | |
77 | + *_; | |
78 | + | |
79 | +cregex http_header_regex_cookie | |
80 | += _ln >> (s1 = icase("cookie") >> ":" >> *~_ln); | |
81 | + | |
82 | +cregex http_header_regex_content_length | |
83 | += _ln >> (s1 = icase("content-length") >> ":" >> *~_ln); | |
84 | + | |
85 | +cregex http_header_regex_x_forwarded_for | |
86 | += _ln >> (s1 = icase("x-forwarded-for") >> ":" >> *~_ln); | |
87 | + | |
88 | +cregex http_header_regex_all | |
89 | += _ln >> (s1 = *_ >> ~_ln) >> repeat<2>(_ln); | |
90 | + | |
91 | +cregex http_header_regex_none | |
92 | += _ln >> (s1 = _ln); | |
93 | + | |
94 | +//! check http method function | |
95 | +//! @param const char* buffer | |
96 | +//! @param const size_t buffer_len | |
97 | +//! @return CHECK_RESULT_TAG http method is valid | |
98 | +l7vs::http_protocol_module_base::CHECK_RESULT_TAG | |
99 | +l7vs::http_protocol_module_base::check_http_method(const char *buffer, | |
100 | + const size_t buffer_len) | |
101 | +{ | |
102 | + | |
103 | + //---------- DEBUG LOG START ------------------------------ | |
104 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
105 | + boost::format outform("function in : [check_http_method] : " | |
106 | + "buffer_len = [%d]"); | |
107 | + | |
108 | + outform % buffer_len; | |
109 | + | |
110 | + putLogDebug(0, | |
111 | + outform.str(), | |
112 | + __FILE__, | |
113 | + __LINE__); | |
114 | + } | |
115 | + //---------- DEBUG LOG END ------------------------------ | |
116 | + | |
117 | + l7vs::http_protocol_module_base::CHECK_RESULT_TAG check_result = CHECK_OK; | |
118 | + | |
119 | + size_t line_length = 0; | |
120 | + | |
121 | + if (likely(buffer != NULL)) { | |
122 | + | |
123 | + for (line_length = 0; line_length < buffer_len; line_length++) { | |
124 | + if (unlikely(buffer[line_length] == '\r' || buffer[line_length] == '\n')) | |
125 | + break; | |
126 | + } | |
127 | + | |
128 | + if (likely(line_length < buffer_len)) { | |
129 | + char *target = const_cast<char *>(buffer); | |
130 | + char backup_c = target[line_length]; | |
131 | + target[line_length] = '\0'; | |
132 | + (regex_match(target, method_regex)) | |
133 | + ? check_result = CHECK_OK | |
134 | + : check_result = CHECK_NG; | |
135 | + target[line_length] = backup_c; | |
136 | + } else { | |
137 | + check_result = CHECK_IMPOSSIBLE; | |
138 | + } | |
139 | + } else { | |
140 | + | |
141 | + check_result = CHECK_NG; | |
142 | + | |
143 | + } | |
144 | + | |
145 | + //---------- DEBUG LOG START ------------------------------ | |
146 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
147 | + boost::format outform("function out : [check_http_method] : " | |
148 | + "check_result = [%d]"); | |
149 | + | |
150 | + outform % check_result; | |
151 | + | |
152 | + putLogDebug(1, | |
153 | + outform.str(), | |
154 | + __FILE__, | |
155 | + __LINE__); | |
156 | + } | |
157 | + //---------- DEBUG LOG END ------------------------------ | |
158 | + | |
159 | + return check_result; | |
160 | + | |
161 | +} | |
162 | + | |
163 | +//! check http version function | |
164 | +//! @param const char* buffer | |
165 | +//! @param const size_t buffer_len | |
166 | +//! @return CHECK_RESULT_TAG http version 1.0 or 1.1 | |
167 | +l7vs::http_protocol_module_base::CHECK_RESULT_TAG | |
168 | +l7vs::http_protocol_module_base::check_http_version(const char *buffer, | |
169 | + const size_t buffer_len) | |
170 | +{ | |
171 | + | |
172 | + //---------- DEBUG LOG START ------------------------------ | |
173 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
174 | + boost::format outform("function in : [check_http_version] : " | |
175 | + "buffer_len = [%d]"); | |
176 | + | |
177 | + outform % buffer_len; | |
178 | + | |
179 | + putLogDebug(2, | |
180 | + outform.str(), | |
181 | + __FILE__, | |
182 | + __LINE__); | |
183 | + } | |
184 | + //---------- DEBUG LOG END ------------------------------ | |
185 | + | |
186 | + l7vs::http_protocol_module_base::CHECK_RESULT_TAG check_result = CHECK_OK; | |
187 | + | |
188 | + size_t line_length = 0; | |
189 | + | |
190 | + if (likely(buffer != NULL)) { | |
191 | + for (line_length = 0; line_length < buffer_len; line_length++) { | |
192 | + if (unlikely(buffer[line_length] == '\r' || buffer[line_length] == '\n')) | |
193 | + break; | |
194 | + } | |
195 | + | |
196 | + if (likely(line_length < buffer_len)) { | |
197 | + char *target = const_cast<char *>(buffer); | |
198 | + char backup_c = target[line_length]; | |
199 | + target[line_length] = '\0'; | |
200 | + | |
201 | + if (!regex_match(target, version_regex_request) && | |
202 | + !regex_match(target, version_regex_response)) check_result = CHECK_NG; | |
203 | + | |
204 | + target[line_length] = backup_c; | |
205 | + | |
206 | + } else { | |
207 | + check_result = CHECK_IMPOSSIBLE; | |
208 | + } | |
209 | + } else { | |
210 | + check_result = CHECK_NG; | |
211 | + } | |
212 | + | |
213 | + //---------- DEBUG LOG START ------------------------------ | |
214 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
215 | + boost::format outform("function out : [check_http_version] : " | |
216 | + "check_result = [%d]"); | |
217 | + | |
218 | + outform % check_result; | |
219 | + | |
220 | + putLogDebug(3, | |
221 | + outform.str(), | |
222 | + __FILE__, | |
223 | + __LINE__); | |
224 | + } | |
225 | + //---------- DEBUG LOG END ------------------------------ | |
226 | + | |
227 | + return check_result; | |
228 | + | |
229 | +} | |
230 | + | |
231 | +//! check http status code function | |
232 | +//! @param const char* buffer | |
233 | +//! @param const size_t buffer_len | |
234 | +//! @return CHECK_RESULT_TAG status code is normal or error | |
235 | +l7vs::http_protocol_module_base::CHECK_RESULT_TAG | |
236 | +l7vs::http_protocol_module_base::check_status_code(const char *buffer, | |
237 | + const size_t buffer_len) | |
238 | +{ | |
239 | + | |
240 | + //---------- DEBUG LOG START ------------------------------ | |
241 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
242 | + boost::format outform("function in : [check_status_code] : " | |
243 | + "buffer_len = [%d]"); | |
244 | + | |
245 | + outform % buffer_len; | |
246 | + | |
247 | + putLogDebug(4, | |
248 | + outform.str(), | |
249 | + __FILE__, | |
250 | + __LINE__); | |
251 | + } | |
252 | + //---------- DEBUG LOG END ------------------------------ | |
253 | + | |
254 | + l7vs::http_protocol_module_base::CHECK_RESULT_TAG check_result = CHECK_OK; | |
255 | + | |
256 | + size_t line_length = 0; | |
257 | + | |
258 | + if (likely(buffer != NULL)) { | |
259 | + for (line_length = 0; line_length < buffer_len; line_length++) { | |
260 | + if (unlikely(buffer[line_length] == '\r' || buffer[line_length] == '\n')) { | |
261 | + break; | |
262 | + } | |
263 | + } | |
264 | + | |
265 | + if (likely(line_length < buffer_len)) { | |
266 | + char *target = const_cast<char *>(buffer); | |
267 | + char backup_c = target[line_length]; | |
268 | + target[line_length] = '\0'; | |
269 | + if (!regex_match(target, status_code_regex_check)) check_result = CHECK_NG; | |
270 | + target[line_length] = backup_c; | |
271 | + } else { | |
272 | + check_result = CHECK_IMPOSSIBLE; | |
273 | + } | |
274 | + } else { | |
275 | + check_result = CHECK_NG; | |
276 | + } | |
277 | + | |
278 | + //---------- DEBUG LOG START ------------------------------ | |
279 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
280 | + boost::format outform("function out : [check_status_code] : " | |
281 | + "check_result = [%d]"); | |
282 | + | |
283 | + outform % check_result; | |
284 | + | |
285 | + putLogDebug(5, | |
286 | + outform.str(), | |
287 | + __FILE__, | |
288 | + __LINE__); | |
289 | + } | |
290 | + //---------- DEBUG LOG END ------------------------------ | |
291 | + | |
292 | + return check_result; | |
293 | + | |
294 | +} | |
295 | + | |
296 | +//! check http method and version function | |
297 | +//! @param const char* buffer | |
298 | +//! @param const size_t buffer_len | |
299 | +//! @return CHECK_RESULT_TAG http method and version is valid | |
300 | +l7vs::http_protocol_module_base::CHECK_RESULT_TAG | |
301 | +l7vs::http_protocol_module_base::check_http_method_and_version( | |
302 | + const char *buffer, | |
303 | + const size_t buffer_len) | |
304 | +{ | |
305 | + | |
306 | + //---------- DEBUG LOG START ------------------------------ | |
307 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
308 | + boost::format outform("function in : [check_http_method_and_version] : " | |
309 | + "buffer_len = [%d]"); | |
310 | + | |
311 | + outform % buffer_len; | |
312 | + | |
313 | + putLogDebug(6, | |
314 | + outform.str(), | |
315 | + __FILE__, | |
316 | + __LINE__); | |
317 | + } | |
318 | + //---------- DEBUG LOG END ------------------------------ | |
319 | + | |
320 | + l7vs::http_protocol_module_base::CHECK_RESULT_TAG check_result = CHECK_OK; | |
321 | + | |
322 | + size_t line_length = 0; | |
323 | + | |
324 | + if (likely(buffer != NULL)) { | |
325 | + for (line_length = 0; line_length < buffer_len; line_length++) { | |
326 | + if (unlikely(buffer[line_length] == '\r' || buffer[line_length] == '\n')) { | |
327 | + break; | |
328 | + } | |
329 | + } | |
330 | + if (likely(line_length < buffer_len)) { | |
331 | + char *target = const_cast<char *>(buffer); | |
332 | + char backup_c = target[line_length]; | |
333 | + target[line_length] = '\0'; | |
334 | + | |
335 | + if (!regex_match(target, method_and_version_regex)) | |
336 | + check_result = CHECK_NG; | |
337 | + | |
338 | + target[line_length] = backup_c; | |
339 | + } else { | |
340 | + check_result = CHECK_NG; | |
341 | + } | |
342 | + } else { | |
343 | + check_result = CHECK_NG; | |
344 | + } | |
345 | + | |
346 | + //---------- DEBUG LOG START ------------------------------ | |
347 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
348 | + boost::format outform("function out : [check_http_method_and_version] : " | |
349 | + "check_result = [%d]"); | |
350 | + | |
351 | + outform % check_result; | |
352 | + | |
353 | + putLogDebug(7, | |
354 | + outform.str(), | |
355 | + __FILE__, | |
356 | + __LINE__); | |
357 | + } | |
358 | + //---------- DEBUG LOG END ------------------------------ | |
359 | + | |
360 | + return check_result; | |
361 | + | |
362 | +} | |
363 | + | |
364 | +//! check http version and status code function | |
365 | +//! @param const char* buffer | |
366 | +//! @param const size_t buffer_len | |
367 | +//! @return CHECK_RESULT_TAG http version and status code is valid | |
368 | +l7vs::http_protocol_module_base::CHECK_RESULT_TAG | |
369 | +l7vs::http_protocol_module_base::check_http_version_and_status_code( | |
370 | + const char *buffer, | |
371 | + const size_t buffer_len) | |
372 | +{ | |
373 | + | |
374 | + //---------- DEBUG LOG START ------------------------------ | |
375 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
376 | + boost::format outform("function in : [check_http_version_and_status_code] : " | |
377 | + "buffer_len = [%d]"); | |
378 | + | |
379 | + outform % buffer_len; | |
380 | + | |
381 | + putLogDebug(8, | |
382 | + outform.str(), | |
383 | + __FILE__, | |
384 | + __LINE__); | |
385 | + } | |
386 | + //---------- DEBUG LOG END ------------------------------ | |
387 | + | |
388 | + l7vs::http_protocol_module_base::CHECK_RESULT_TAG check_result = CHECK_OK; | |
389 | + | |
390 | + size_t line_length = 0; | |
391 | + | |
392 | + if (likely(buffer != NULL)) { | |
393 | + for (line_length = 0; line_length < buffer_len; line_length++) { | |
394 | + if (unlikely(buffer[line_length] == '\r' || buffer[line_length] == '\n')) { | |
395 | + break; | |
396 | + } | |
397 | + } | |
398 | + | |
399 | + if (likely(line_length < buffer_len)) { | |
400 | + char *target = const_cast<char *>(buffer); | |
401 | + char backup_c = target[line_length]; | |
402 | + target[line_length] = '\0'; | |
403 | + if (!regex_match(target, version_and_status_code_regex)) check_result = CHECK_NG; | |
404 | + target[line_length] = backup_c; | |
405 | + } else { | |
406 | + check_result = CHECK_IMPOSSIBLE; | |
407 | + } | |
408 | + } else { | |
409 | + check_result = CHECK_NG; | |
410 | + } | |
411 | + | |
412 | + //---------- DEBUG LOG START ------------------------------ | |
413 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
414 | + boost::format outform("function out : [check_http_version_and_status_code] : " | |
415 | + "check_result = [%d]"); | |
416 | + | |
417 | + outform % check_result; | |
418 | + | |
419 | + putLogDebug(9, | |
420 | + outform.str(), | |
421 | + __FILE__, | |
422 | + __LINE__); | |
423 | + } | |
424 | + //---------- DEBUG LOG END ------------------------------ | |
425 | + | |
426 | + return check_result; | |
427 | + | |
428 | +} | |
429 | + | |
430 | +//! search uri function | |
431 | +//! @param const char* buffer | |
432 | +//! @param const size_t buffer_len | |
433 | +//! @param size_t& uri offset | |
434 | +//! @param size_t& uri length | |
435 | +//! @return bool find is true. not find is false | |
436 | +bool l7vs::http_protocol_module_base::find_uri(const char *buffer, | |
437 | + const size_t buffer_len, | |
438 | + size_t &uri_offset, | |
439 | + size_t &uri_len) | |
440 | +{ | |
441 | + | |
442 | + //---------- DEBUG LOG START ------------------------------ | |
443 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
444 | + boost::format outform("function in : [find_uri] : " | |
445 | + "buffer_len = [%d]"); | |
446 | + | |
447 | + outform % buffer_len; | |
448 | + | |
449 | + putLogDebug(10, | |
450 | + outform.str(), | |
451 | + __FILE__, | |
452 | + __LINE__); | |
453 | + } | |
454 | + //---------- DEBUG LOG END ------------------------------ | |
455 | + | |
456 | + bool find_result = true; | |
457 | + | |
458 | + size_t line_length = 0; | |
459 | + | |
460 | + match_results< const char * > result; | |
461 | + | |
462 | + if (likely(buffer != NULL)) { | |
463 | + | |
464 | + for (line_length = 0; line_length < buffer_len; line_length++) { | |
465 | + | |
466 | + if (unlikely(buffer[line_length] == '\r' || buffer[line_length] == '\n')) { | |
467 | + | |
468 | + break; | |
469 | + | |
470 | + } | |
471 | + | |
472 | + } | |
473 | + | |
474 | + if (likely(line_length < buffer_len)) { | |
475 | + char *target = const_cast<char *>(buffer); | |
476 | + char backup_c = target[line_length]; | |
477 | + find_result = regex_search(target, result, uri_regex); | |
478 | + if (find_result) { | |
479 | + uri_offset = result.position(1); | |
480 | + uri_len = result.length(1); | |
481 | + } | |
482 | + target[line_length] = backup_c; | |
483 | + } else { | |
484 | + find_result = false; | |
485 | + } | |
486 | + } else { | |
487 | + find_result = false; | |
488 | + } | |
489 | + | |
490 | + //---------- DEBUG LOG START ------------------------------ | |
491 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
492 | + boost::format outform("function out : [find_uri] : " | |
493 | + "find_result = [%d], " | |
494 | + "uri_offset = [%d], " | |
495 | + "uri_len = [%d]"); | |
496 | + | |
497 | + outform % find_result % uri_offset % uri_len; | |
498 | + | |
499 | + putLogDebug(11, | |
500 | + outform.str(), | |
501 | + __FILE__, | |
502 | + __LINE__); | |
503 | + } | |
504 | + //---------- DEBUG LOG END ------------------------------ | |
505 | + | |
506 | + return find_result; | |
507 | + | |
508 | +} | |
509 | + | |
510 | +//! search status function | |
511 | +//! @param const char* buffer | |
512 | +//! @param const size_t buffer_len | |
513 | +//! @param size_t& status offset | |
514 | +//! @param size_t& status length | |
515 | +//! @return bool find is true. not find is false | |
516 | +bool l7vs::http_protocol_module_base::find_status_code(const char *buffer, | |
517 | + const size_t buffer_len, | |
518 | + size_t &status_code_offset, | |
519 | + size_t &status_code_len) | |
520 | +{ | |
521 | + | |
522 | + //---------- DEBUG LOG START ------------------------------ | |
523 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
524 | + boost::format outform("function in : [find_status_code] : " | |
525 | + "buffer_len = [%d]"); | |
526 | + | |
527 | + outform % buffer_len; | |
528 | + | |
529 | + putLogDebug(12, | |
530 | + outform.str(), | |
531 | + __FILE__, | |
532 | + __LINE__); | |
533 | + } | |
534 | + //---------- DEBUG LOG END ------------------------------ | |
535 | + | |
536 | + bool find_result = true; | |
537 | + | |
538 | + size_t line_length = 0; | |
539 | + | |
540 | + match_results< const char * > result; | |
541 | + | |
542 | + if (likely(buffer != NULL)) { | |
543 | + | |
544 | + for (line_length = 0; line_length < buffer_len; line_length++) { | |
545 | + if (unlikely(buffer[line_length] == '\r' || buffer[line_length] == '\n')) { | |
546 | + break; | |
547 | + } | |
548 | + } | |
549 | + | |
550 | + if (likely(line_length < buffer_len)) { | |
551 | + char *target = const_cast<char *>(buffer); | |
552 | + char backup_c = target[line_length]; | |
553 | + target[line_length] = '\0'; | |
554 | + find_result = regex_search(target, result, status_code_regex_find); | |
555 | + if (find_result) { | |
556 | + status_code_offset = result.position(1); | |
557 | + status_code_len = result.length(1); | |
558 | + } | |
559 | + target[line_length] = backup_c; | |
560 | + } else { | |
561 | + find_result = false; | |
562 | + } | |
563 | + } else { | |
564 | + find_result = false; | |
565 | + } | |
566 | + | |
567 | + //---------- DEBUG LOG START ------------------------------ | |
568 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
569 | + boost::format outform("function out : [find_status_code] : " | |
570 | + "find_result = [%d], " | |
571 | + "status_code_offset = [%d], " | |
572 | + "status_code_len = [%d]"); | |
573 | + | |
574 | + outform % find_result % status_code_offset % status_code_len; | |
575 | + | |
576 | + putLogDebug(13, | |
577 | + outform.str(), | |
578 | + __FILE__, | |
579 | + __LINE__); | |
580 | + } | |
581 | + //---------- DEBUG LOG END ------------------------------ | |
582 | + | |
583 | + return find_result; | |
584 | + | |
585 | +} | |
586 | + | |
587 | +//! search http header function | |
588 | +//! @param const char* buffer | |
589 | +//! @param const size_t buffer_len | |
590 | +//! @param const string& header name | |
591 | +//! @param size_t& header offset | |
592 | +//! @param size_t& header length | |
593 | +//! @return bool find is true. not find is false | |
594 | +bool l7vs::http_protocol_module_base::find_http_header(const char *buffer, | |
595 | + const size_t buffer_len, | |
596 | + const std::string &http_header_name, | |
597 | + size_t &http_header_offset, | |
598 | + size_t &http_header_len) | |
599 | +{ | |
600 | + | |
601 | + //---------- DEBUG LOG START ------------------------------ | |
602 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
603 | + boost::format outform("function in : [find_http_header] : " | |
604 | + "buffer_len = [%d], " | |
605 | + "http_header_name = [%s]"); | |
606 | + | |
607 | + outform % buffer_len % http_header_name; | |
608 | + | |
609 | + putLogDebug(14, | |
610 | + outform.str(), | |
611 | + __FILE__, | |
612 | + __LINE__); | |
613 | + } | |
614 | + //---------- DEBUG LOG END ------------------------------ | |
615 | + | |
616 | + cregex http_header_regex; | |
617 | + | |
618 | + bool find_result = true; | |
619 | + | |
620 | + size_t count = 0; | |
621 | + size_t header_begin = 0; | |
622 | + size_t header_end = 0; | |
623 | + size_t header_length = 0; | |
624 | + | |
625 | + int header_begin_flag = 0; | |
626 | + int header_end_flag = 0; | |
627 | + | |
628 | + match_results< const char * > result; | |
629 | + | |
630 | + if (likely(buffer != NULL)) { | |
631 | + | |
632 | + for (count = 0; count < buffer_len; count++) { | |
633 | + | |
634 | + if (unlikely(buffer[count] == '\r' || buffer[count] == '\n')) { | |
635 | + | |
636 | + if (unlikely(header_begin_flag == 0)) { | |
637 | + | |
638 | + header_begin = count; | |
639 | + header_begin_flag = 1; | |
640 | + | |
641 | + } | |
642 | + | |
643 | + if (likely(count > 0)) { | |
644 | + | |
645 | + if (unlikely((buffer[count-1] == '\r' && buffer[count] == '\r') || | |
646 | + (buffer[count-1] == '\n' && buffer[count] == '\n'))) { | |
647 | + | |
648 | + header_end = count; | |
649 | + header_end_flag = 1; | |
650 | + break; | |
651 | + | |
652 | + } | |
653 | + } | |
654 | + | |
655 | + if (likely(count > 2)) { | |
656 | + | |
657 | + if (unlikely(buffer[count-3] == '\r' && buffer[count-2] == '\n' && | |
658 | + buffer[count-1] == '\r' && buffer[count] == '\n')) { | |
659 | + | |
660 | + header_end = count; | |
661 | + header_end_flag = 1; | |
662 | + break; | |
663 | + | |
664 | + } | |
665 | + } | |
666 | + } | |
667 | + } | |
668 | + | |
669 | + if (likely(header_begin_flag == 1 && header_end_flag == 1)) { | |
670 | + | |
671 | + header_length = header_end - header_begin + 1; | |
672 | + char *ptr = const_cast<char *>(buffer) + header_begin; | |
673 | + char backup_c = *(ptr + header_length); | |
674 | + *(ptr + header_length) = '\0'; | |
675 | + | |
676 | + if (http_header_name.length() > 0) { | |
677 | + http_header_regex = _ln >> (s1 = icase(http_header_name) >> ":" >> *~_ln); | |
678 | + find_result = regex_search(ptr , result, http_header_regex); | |
679 | + if (find_result) { | |
680 | + http_header_offset = result.position(1) + header_begin; | |
681 | + http_header_len = result.length(1); | |
682 | + } | |
683 | + } else { | |
684 | + http_header_regex = _ln >> (s1 = *_ >> ~_ln) >> repeat<2>(_ln); | |
685 | + find_result = regex_search(ptr, result, http_header_regex); | |
686 | + if (find_result) { | |
687 | + http_header_offset = result.position(1) + header_begin; | |
688 | + http_header_len = result.length(1); | |
689 | + } else { | |
690 | + http_header_regex = _ln >> (s1 = _ln); | |
691 | + find_result = regex_search(ptr, result, http_header_regex); | |
692 | + if (find_result) { | |
693 | + http_header_offset = result.position(1) + header_begin; | |
694 | + http_header_len = 0; | |
695 | + } | |
696 | + } | |
697 | + } | |
698 | + *(ptr + header_length) = backup_c; | |
699 | + } else { | |
700 | + find_result = false; | |
701 | + } | |
702 | + } else { | |
703 | + find_result = false; | |
704 | + } | |
705 | + | |
706 | + //---------- DEBUG LOG START ------------------------------ | |
707 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
708 | + boost::format outform("function out : [find_http_header] : " | |
709 | + "find_result = [%d], " | |
710 | + "http_header_offset = [%d], " | |
711 | + "http_header_len = [%d]"); | |
712 | + | |
713 | + outform % find_result % http_header_offset % http_header_len; | |
714 | + | |
715 | + putLogDebug(15, | |
716 | + outform.str(), | |
717 | + __FILE__, | |
718 | + __LINE__); | |
719 | + } | |
720 | + //---------- DEBUG LOG END ------------------------------ | |
721 | + | |
722 | + return find_result; | |
723 | + | |
724 | +} | |
725 | + | |
726 | +//! search http header Cookie function | |
727 | +//! @param const char* buffer | |
728 | +//! @param const size_t buffer_len | |
729 | +//! @param size_t& header offset | |
730 | +//! @param size_t& header length | |
731 | +//! @return bool find is true. not find is false | |
732 | +bool l7vs::http_protocol_module_base::find_http_header_cookie( | |
733 | + const char *buffer, | |
734 | + const size_t buffer_len, | |
735 | + size_t &http_header_offset, | |
736 | + size_t &http_header_len) | |
737 | +{ | |
738 | + | |
739 | + //---------- DEBUG LOG START ------------------------------ | |
740 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
741 | + boost::format outform("function in : [find_http_header_cookie] : " | |
742 | + "buffer_len = [%d]"); | |
743 | + | |
744 | + outform % buffer_len; | |
745 | + | |
746 | + putLogDebug(16, | |
747 | + outform.str(), | |
748 | + __FILE__, | |
749 | + __LINE__); | |
750 | + } | |
751 | + //---------- DEBUG LOG END ------------------------------ | |
752 | + | |
753 | + bool find_result = true; | |
754 | + | |
755 | + size_t count = 0; | |
756 | + size_t header_begin = 0; | |
757 | + size_t header_end = 0; | |
758 | + size_t header_length = 0; | |
759 | + | |
760 | + int header_begin_flag = 0; | |
761 | + int header_end_flag = 0; | |
762 | + | |
763 | + match_results< const char * > result; | |
764 | + | |
765 | + if (likely(buffer != NULL)) { | |
766 | + for (count = 0; count < buffer_len; count++) { | |
767 | + if (unlikely(buffer[count] == '\r' || buffer[count] == '\n')) { | |
768 | + if (unlikely(header_begin_flag == 0)) { | |
769 | + header_begin = count; | |
770 | + header_begin_flag = 1; | |
771 | + } | |
772 | + if (likely(count > 0)) { | |
773 | + if (unlikely((buffer[count-1] == '\r' && buffer[count] == '\r') || | |
774 | + (buffer[count-1] == '\n' && buffer[count] == '\n'))) { | |
775 | + header_end = count; | |
776 | + header_end_flag = 1; | |
777 | + break; | |
778 | + } | |
779 | + } | |
780 | + if (likely(count > 2)) { | |
781 | + if (unlikely(buffer[count-3] == '\r' && buffer[count-2] == '\n' && | |
782 | + buffer[count-1] == '\r' && buffer[count] == '\n')) { | |
783 | + header_end = count; | |
784 | + header_end_flag = 1; | |
785 | + break; | |
786 | + | |
787 | + } | |
788 | + } | |
789 | + } | |
790 | + } | |
791 | + | |
792 | + if (likely(header_begin_flag == 1 && header_end_flag == 1)) { | |
793 | + header_length = header_end - header_begin + 1; | |
794 | + char *ptr = const_cast<char *>(buffer) + header_begin; | |
795 | + char backup_c = *(ptr + header_length); | |
796 | + *(ptr + header_length) = '\0'; | |
797 | + | |
798 | + find_result = regex_search(ptr, result, http_header_regex_cookie); | |
799 | + if (find_result) { | |
800 | + http_header_offset = result.position(1) + header_begin; | |
801 | + http_header_len = result.length(1); | |
802 | + } | |
803 | + *(ptr + header_length) = backup_c; | |
804 | + } else { | |
805 | + find_result = false; | |
806 | + } | |
807 | + } else { | |
808 | + find_result = false; | |
809 | + } | |
810 | + | |
811 | + //---------- DEBUG LOG START ------------------------------ | |
812 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
813 | + boost::format outform("function out : [find_http_header_cookie] : " | |
814 | + "find_result = [%d], " | |
815 | + "http_header_offset = [%d], " | |
816 | + "http_header_len = [%d]"); | |
817 | + | |
818 | + outform % find_result % http_header_offset % http_header_len; | |
819 | + | |
820 | + putLogDebug(17, | |
821 | + outform.str(), | |
822 | + __FILE__, | |
823 | + __LINE__); | |
824 | + } | |
825 | + //---------- DEBUG LOG END ------------------------------ | |
826 | + | |
827 | + return find_result; | |
828 | + | |
829 | +} | |
830 | + | |
831 | +//! search http header Content_Length function | |
832 | +//! @param const char* buffer | |
833 | +//! @param const size_t buffer_len | |
834 | +//! @param size_t& header offset | |
835 | +//! @param size_t& header length | |
836 | +//! @return bool find is true. not find is false | |
837 | +bool l7vs::http_protocol_module_base::find_http_header_content_length( | |
838 | + const char *buffer, | |
839 | + const size_t buffer_len, | |
840 | + size_t &http_header_offset, | |
841 | + size_t &http_header_len) | |
842 | +{ | |
843 | + | |
844 | + //---------- DEBUG LOG START ------------------------------ | |
845 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
846 | + boost::format outform("function in : [find_http_header_content_length] : " | |
847 | + "buffer_len = [%d]"); | |
848 | + | |
849 | + outform % buffer_len; | |
850 | + | |
851 | + putLogDebug(18, | |
852 | + outform.str(), | |
853 | + __FILE__, | |
854 | + __LINE__); | |
855 | + } | |
856 | + //---------- DEBUG LOG END ------------------------------ | |
857 | + | |
858 | + bool find_result = true; | |
859 | + | |
860 | + size_t count = 0; | |
861 | + size_t header_begin = 0; | |
862 | + size_t header_end = 0; | |
863 | + size_t header_length = 0; | |
864 | + | |
865 | + int header_begin_flag = 0; | |
866 | + int header_end_flag = 0; | |
867 | + | |
868 | + match_results< const char * > result; | |
869 | + | |
870 | + if (likely(buffer != NULL)) { | |
871 | + for (count = 0; count < buffer_len; count++) { | |
872 | + if (unlikely(buffer[count] == '\r' || buffer[count] == '\n')) { | |
873 | + if (unlikely(header_begin_flag == 0)) { | |
874 | + header_begin = count; | |
875 | + header_begin_flag = 1; | |
876 | + } | |
877 | + if (likely(count > 0)) { | |
878 | + if (unlikely((buffer[count-1] == '\r' && buffer[count] == '\r') || | |
879 | + (buffer[count-1] == '\n' && buffer[count] == '\n'))) { | |
880 | + header_end = count; | |
881 | + header_end_flag = 1; | |
882 | + break; | |
883 | + } | |
884 | + } | |
885 | + if (likely(count > 2)) { | |
886 | + if (unlikely(buffer[count-3] == '\r' && buffer[count-2] == '\n' && | |
887 | + buffer[count-1] == '\r' && buffer[count] == '\n')) { | |
888 | + header_end = count; | |
889 | + header_end_flag = 1; | |
890 | + break; | |
891 | + } | |
892 | + } | |
893 | + } | |
894 | + } | |
895 | + | |
896 | + if (likely(header_begin_flag == 1 && header_end_flag == 1)) { | |
897 | + header_length = header_end - header_begin + 1; | |
898 | + | |
899 | + char *ptr = const_cast<char *>(buffer) + header_begin; | |
900 | + char backup_c = *(ptr + header_length); | |
901 | + *(ptr + header_length) = '\0'; | |
902 | + | |
903 | + find_result = regex_search(ptr, result, http_header_regex_content_length); | |
904 | + if (find_result) { | |
905 | + http_header_offset = result.position(1) + header_begin; | |
906 | + http_header_len = result.length(1); | |
907 | + } | |
908 | + | |
909 | + *(ptr + header_length) = backup_c; | |
910 | + } else { | |
911 | + | |
912 | + find_result = false; | |
913 | + | |
914 | + } | |
915 | + } else { | |
916 | + | |
917 | + find_result = false; | |
918 | + | |
919 | + } | |
920 | + | |
921 | + //---------- DEBUG LOG START ------------------------------ | |
922 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
923 | + boost::format outform("function out : [find_http_header_content_length] : " | |
924 | + "find_result = [%d], " | |
925 | + "http_header_offset = [%d], " | |
926 | + "http_header_len = [%d]"); | |
927 | + | |
928 | + outform % find_result % http_header_offset % http_header_len; | |
929 | + | |
930 | + putLogDebug(19, | |
931 | + outform.str(), | |
932 | + __FILE__, | |
933 | + __LINE__); | |
934 | + } | |
935 | + //---------- DEBUG LOG END ------------------------------ | |
936 | + | |
937 | + return find_result; | |
938 | + | |
939 | +} | |
940 | + | |
941 | +//! search http header X_Forwarded_For function | |
942 | +//! @param const char* buffer | |
943 | +//! @param const size_t buffer_len | |
944 | +//! @param size_t& header offset | |
945 | +//! @param size_t& header length | |
946 | +//! @return bool find is true. not find is false | |
947 | +bool l7vs::http_protocol_module_base::find_http_header_x_forwarded_for( | |
948 | + const char *buffer, | |
949 | + const size_t buffer_len, | |
950 | + size_t &http_header_offset, | |
951 | + size_t &http_header_len) | |
952 | +{ | |
953 | + | |
954 | + //---------- DEBUG LOG START ------------------------------ | |
955 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
956 | + boost::format outform("function in : [find_http_header_x_forwarded_for] : " | |
957 | + "buffer_len = [%d]"); | |
958 | + | |
959 | + outform % buffer_len; | |
960 | + | |
961 | + putLogDebug(20, | |
962 | + outform.str(), | |
963 | + __FILE__, | |
964 | + __LINE__); | |
965 | + } | |
966 | + //---------- DEBUG LOG END ------------------------------ | |
967 | + | |
968 | + bool find_result = true; | |
969 | + | |
970 | + size_t count = 0; | |
971 | + size_t header_begin = 0; | |
972 | + size_t header_end = 0; | |
973 | + size_t header_length = 0; | |
974 | + | |
975 | + int header_begin_flag = 0; | |
976 | + int header_end_flag = 0; | |
977 | + | |
978 | + match_results< const char * > result; | |
979 | + | |
980 | + if (likely(buffer != NULL)) { | |
981 | + for (count = 0; count < buffer_len; count++) { | |
982 | + if (unlikely(buffer[count] == '\r' || buffer[count] == '\n')) { | |
983 | + if (unlikely(header_begin_flag == 0)) { | |
984 | + header_begin = count; | |
985 | + header_begin_flag = 1; | |
986 | + } | |
987 | + if (likely(count > 0)) { | |
988 | + if (unlikely((buffer[count-1] == '\r' && buffer[count] == '\r') || | |
989 | + (buffer[count-1] == '\n' && buffer[count] == '\n'))) { | |
990 | + header_end = count; | |
991 | + header_end_flag = 1; | |
992 | + break; | |
993 | + } | |
994 | + } | |
995 | + | |
996 | + if (likely(count > 2)) { | |
997 | + if (unlikely(buffer[count-3] == '\r' && buffer[count-2] == '\n' && | |
998 | + buffer[count-1] == '\r' && buffer[count] == '\n')) { | |
999 | + header_end = count; | |
1000 | + header_end_flag = 1; | |
1001 | + break; | |
1002 | + | |
1003 | + } | |
1004 | + } | |
1005 | + } | |
1006 | + } | |
1007 | + | |
1008 | + if (likely(header_begin_flag == 1 && header_end_flag == 1)) { | |
1009 | + | |
1010 | + header_length = header_end - header_begin + 1; | |
1011 | + char *ptr = const_cast<char *>(buffer) + header_begin; | |
1012 | + char backup_c = *(ptr + header_length); | |
1013 | + *(ptr + header_length) = '\0'; | |
1014 | + | |
1015 | + find_result = regex_search(ptr, result, http_header_regex_x_forwarded_for); | |
1016 | + if (find_result == true) { | |
1017 | + http_header_offset = result.position(1) + header_begin; | |
1018 | + http_header_len = result.length(1); | |
1019 | + } | |
1020 | + | |
1021 | + *(ptr + header_length) = backup_c; | |
1022 | + } else { | |
1023 | + | |
1024 | + find_result = false; | |
1025 | + | |
1026 | + } | |
1027 | + } else { | |
1028 | + | |
1029 | + find_result = false; | |
1030 | + | |
1031 | + } | |
1032 | + | |
1033 | + //---------- DEBUG LOG START ------------------------------ | |
1034 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1035 | + boost::format outform("function out : [find_http_header_x_forwarded_for] : " | |
1036 | + "find_result = [%d], " | |
1037 | + "http_header_offset = [%d], " | |
1038 | + "http_header_len = [%d]"); | |
1039 | + | |
1040 | + outform % find_result % http_header_offset % http_header_len; | |
1041 | + | |
1042 | + putLogDebug(21, | |
1043 | + outform.str(), | |
1044 | + __FILE__, | |
1045 | + __LINE__); | |
1046 | + } | |
1047 | + //---------- DEBUG LOG END ------------------------------ | |
1048 | + | |
1049 | + return find_result; | |
1050 | + | |
1051 | +} | |
1052 | + | |
1053 | +//! search http header all function | |
1054 | +//! @param const char* buffer | |
1055 | +//! @param const size_t buffer_len | |
1056 | +//! @param size_t& header offset | |
1057 | +//! @param size_t& header length | |
1058 | +//! @return bool find is true. not find is false | |
1059 | +bool l7vs::http_protocol_module_base::find_http_header_all( | |
1060 | + const char *buffer, | |
1061 | + const size_t buffer_len, | |
1062 | + size_t &http_header_offset, | |
1063 | + size_t &http_header_len) | |
1064 | +{ | |
1065 | + | |
1066 | + //---------- DEBUG LOG START ------------------------------ | |
1067 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1068 | + boost::format outform("function in : [find_http_header_all] : " | |
1069 | + "buffer_len = [%d]"); | |
1070 | + | |
1071 | + outform % buffer_len; | |
1072 | + | |
1073 | + putLogDebug(22, | |
1074 | + outform.str(), | |
1075 | + __FILE__, | |
1076 | + __LINE__); | |
1077 | + } | |
1078 | + //---------- DEBUG LOG END ------------------------------ | |
1079 | + | |
1080 | + bool find_result = true; | |
1081 | + | |
1082 | + size_t count = 0; | |
1083 | + size_t header_begin = 0; | |
1084 | + size_t header_end = 0; | |
1085 | + size_t header_length = 0; | |
1086 | + | |
1087 | + int header_begin_flag = 0; | |
1088 | + int header_end_flag = 0; | |
1089 | + | |
1090 | + match_results< const char * > result; | |
1091 | + | |
1092 | + if (likely(buffer != NULL)) { | |
1093 | + for (count = 0; count < buffer_len; count++) { | |
1094 | + if (unlikely(buffer[count] == '\r' || buffer[count] == '\n')) { | |
1095 | + if (unlikely(header_begin_flag == 0)) { | |
1096 | + header_begin = count; | |
1097 | + header_begin_flag = 1; | |
1098 | + } | |
1099 | + | |
1100 | + if (likely(count > 0)) { | |
1101 | + if (unlikely((buffer[count-1] == '\r' && buffer[count] == '\r') || | |
1102 | + (buffer[count-1] == '\n' && buffer[count] == '\n'))) { | |
1103 | + header_end = count; | |
1104 | + header_end_flag = 1; | |
1105 | + break; | |
1106 | + } | |
1107 | + } | |
1108 | + | |
1109 | + if (likely(count > 2)) { | |
1110 | + if (unlikely(buffer[count-3] == '\r' && buffer[count-2] == '\n' && | |
1111 | + buffer[count-1] == '\r' && buffer[count] == '\n')) { | |
1112 | + header_end = count; | |
1113 | + header_end_flag = 1; | |
1114 | + break; | |
1115 | + } | |
1116 | + } | |
1117 | + } | |
1118 | + } | |
1119 | + | |
1120 | + if (likely(header_begin_flag == 1 && header_end_flag == 1)) { | |
1121 | + header_length = header_end - header_begin + 1; | |
1122 | + char *ptr = const_cast<char *>(buffer) + header_begin; | |
1123 | + char backup_c = *(ptr + header_length); | |
1124 | + *(ptr + header_length) = '\0'; | |
1125 | + | |
1126 | + find_result = regex_search(ptr, result, http_header_regex_all); | |
1127 | + | |
1128 | + if (find_result) { | |
1129 | + http_header_offset = result.position(1) + header_begin; | |
1130 | + http_header_len = result.length(1); | |
1131 | + } else { | |
1132 | + find_result = regex_search(ptr, result, http_header_regex_none); | |
1133 | + if (find_result == true) { | |
1134 | + http_header_offset = result.position(1) + header_begin; | |
1135 | + http_header_len = 0; | |
1136 | + } | |
1137 | + } | |
1138 | + *(ptr + header_length) = backup_c; | |
1139 | + } else { | |
1140 | + | |
1141 | + find_result = false; | |
1142 | + | |
1143 | + } | |
1144 | + } else { | |
1145 | + | |
1146 | + find_result = false; | |
1147 | + | |
1148 | + } | |
1149 | + | |
1150 | + //---------- DEBUG LOG START ------------------------------ | |
1151 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1152 | + boost::format outform("function out : [find_http_header_all] : " | |
1153 | + "find_result = [%d], " | |
1154 | + "http_header_offset = [%d], " | |
1155 | + "http_header_len = [%d]"); | |
1156 | + | |
1157 | + outform % find_result % http_header_offset % http_header_len; | |
1158 | + | |
1159 | + putLogDebug(23, | |
1160 | + outform.str(), | |
1161 | + __FILE__, | |
1162 | + __LINE__); | |
1163 | + } | |
1164 | + //---------- DEBUG LOG END ------------------------------ | |
1165 | + | |
1166 | + return find_result; | |
1167 | + | |
1168 | +} | |
1169 | + | |
1170 | +//! check http get method | |
1171 | +//! @param const char* buffer | |
1172 | +//! @return bool get method is true. other is false | |
1173 | +bool l7vs::http_protocol_module_base::is_get_request(const char *buffer) | |
1174 | +{ | |
1175 | + //---------- DEBUG LOG START ------------------------------ | |
1176 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1177 | + putLogDebug(24, | |
1178 | + "function in : [is_get_request].", | |
1179 | + __FILE__, | |
1180 | + __LINE__); | |
1181 | + } | |
1182 | + //---------- DEBUG LOG END ------------------------------ | |
1183 | + | |
1184 | + bool check_result = false; | |
1185 | + | |
1186 | + if (likely(buffer != NULL)) { | |
1187 | + if (strncmp("GET", buffer, 3) == 0) { | |
1188 | + check_result = true; | |
1189 | + } | |
1190 | + } | |
1191 | + | |
1192 | + //---------- DEBUG LOG START ------------------------------ | |
1193 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1194 | + boost::format outform("function out : [is_get_request] : " | |
1195 | + "check_result = [%d]"); | |
1196 | + | |
1197 | + outform % check_result; | |
1198 | + | |
1199 | + putLogDebug(25, | |
1200 | + outform.str(), | |
1201 | + __FILE__, | |
1202 | + __LINE__); | |
1203 | + } | |
1204 | + //---------- DEBUG LOG END ------------------------------ | |
1205 | + | |
1206 | + return check_result; | |
1207 | +} | |
1208 | + | |
1209 | +//! check http post method | |
1210 | +//! @param const char* buffer | |
1211 | +//! @return bool post method is true. other is false | |
1212 | +bool l7vs::http_protocol_module_base::is_post_request(const char *buffer) | |
1213 | +{ | |
1214 | + //---------- DEBUG LOG START ------------------------------ | |
1215 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1216 | + putLogDebug(26, | |
1217 | + "function in : [is_post_request].", | |
1218 | + __FILE__, | |
1219 | + __LINE__); | |
1220 | + } | |
1221 | + //---------- DEBUG LOG END ------------------------------ | |
1222 | + | |
1223 | + bool check_result = false; | |
1224 | + | |
1225 | + if (likely(buffer != NULL)) { | |
1226 | + if (strncmp("POST", buffer, 4) == 0) { | |
1227 | + check_result = true; | |
1228 | + } | |
1229 | + } | |
1230 | + | |
1231 | + //---------- DEBUG LOG START ------------------------------ | |
1232 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1233 | + boost::format outform("function out : [is_post_request] : " | |
1234 | + "check_result = [%d]"); | |
1235 | + | |
1236 | + outform % check_result; | |
1237 | + | |
1238 | + putLogDebug(27, | |
1239 | + outform.str(), | |
1240 | + __FILE__, | |
1241 | + __LINE__); | |
1242 | + } | |
1243 | + //---------- DEBUG LOG END ------------------------------ | |
1244 | + | |
1245 | + return check_result; | |
1246 | +} | |
1247 | + | |
1248 | +//! increment http statistics | |
1249 | +//! @param const char* buffer | |
1250 | +void l7vs::http_protocol_module_base::increment_stats(const char *buffer) | |
1251 | +{ | |
1252 | + //---------- DEBUG LOG START ------------------------------ | |
1253 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1254 | + boost::format outform("function in : [increment_stats] : " | |
1255 | + "http_get_requests = [%d], " | |
1256 | + "http_post_requests = [%d], " | |
1257 | + "http_requests = [%d]"); | |
1258 | + | |
1259 | + outform % http_stats_info.http_get_requests.get() % | |
1260 | + http_stats_info.http_post_requests.get() % | |
1261 | + http_stats_info.http_requests.get(); | |
1262 | + putLogDebug(28, | |
1263 | + outform.str(), | |
1264 | + __FILE__, | |
1265 | + __LINE__); | |
1266 | + } | |
1267 | + //---------- DEBUG LOG END ------------------------------ | |
1268 | + | |
1269 | + if (buffer != NULL && statistic == true) { | |
1270 | + if (is_get_request(buffer)) { | |
1271 | + http_stats_info.http_get_requests++; | |
1272 | + } else if (is_post_request(buffer)) { | |
1273 | + http_stats_info.http_post_requests++; | |
1274 | + } | |
1275 | + | |
1276 | + http_stats_info.http_requests++; | |
1277 | + } | |
1278 | + | |
1279 | + //---------- DEBUG LOG START ------------------------------ | |
1280 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
1281 | + boost::format outform("function out : [increment_stats] : " | |
1282 | + "http_get_requests = [%d], " | |
1283 | + "http_post_requests = [%d], " | |
1284 | + "http_requests = [%d]"); | |
1285 | + | |
1286 | + outform % http_stats_info.http_get_requests.get() % | |
1287 | + http_stats_info.http_post_requests.get() % | |
1288 | + http_stats_info.http_requests.get(); | |
1289 | + | |
1290 | + putLogDebug(29, | |
1291 | + outform.str(), | |
1292 | + __FILE__, | |
1293 | + __LINE__); | |
1294 | + } | |
1295 | + //---------- DEBUG LOG END ------------------------------ | |
1296 | +} |
@@ -0,0 +1,164 @@ | ||
1 | +/* | |
2 | + * @file http_protocol_module_base.h | |
3 | + * @brief shared object http protocol module abstract 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 | +#ifndef HTTP_PROTOCOL_MODULE_BASE_H | |
25 | +#define HTTP_PROTOCOL_MODULE_BASE_H | |
26 | + | |
27 | +#include "protocol_module_base.h" | |
28 | + | |
29 | +namespace l7vs | |
30 | +{ | |
31 | + | |
32 | +class http_protocol_module_base : public protocol_module_base | |
33 | +{ | |
34 | +protected: | |
35 | + //! @enum CHECK_RESULT_TAG | |
36 | + //! @brief check tag is return to http protocol module. | |
37 | + enum CHECK_RESULT_TAG { | |
38 | + CHECK_OK = 0, //!< check ok | |
39 | + CHECK_NG, //!< check NG | |
40 | + CHECK_IMPOSSIBLE //!< check impossible | |
41 | + }; | |
42 | + | |
43 | + //! check http method function | |
44 | + //! @param const char* buffer | |
45 | + //! @param const size_t buffer_len | |
46 | + //! @return CHECK_RESULT_TAG http method is valid | |
47 | + CHECK_RESULT_TAG check_http_method(const char *, const size_t); | |
48 | + | |
49 | + //! check http version function | |
50 | + //! @param const char* buffer | |
51 | + //! @param const size_t buffer_len | |
52 | + //! @return CHECK_RESULT_TAG http version 1.0 or 1.1 | |
53 | + CHECK_RESULT_TAG check_http_version(const char *, const size_t); | |
54 | + | |
55 | + //! check http status code function | |
56 | + //! @param const char* buffer | |
57 | + //! @param const size_t buffer_len | |
58 | + //! @return CHECK_RESULT_TAG status code is normal or error | |
59 | + CHECK_RESULT_TAG check_status_code(const char *, const size_t); | |
60 | + | |
61 | + //! check http method and version function | |
62 | + //! @param const char* buffer | |
63 | + //! @param const size_t buffer_len | |
64 | + //! @return CHECK_RESULT_TAG http method and version is valid | |
65 | + CHECK_RESULT_TAG check_http_method_and_version(const char *, const size_t); | |
66 | + | |
67 | + //! check http version and status code function | |
68 | + //! @param const char* buffer | |
69 | + //! @param const size_t buffer_len | |
70 | + //! @return CHECK_RESULT_TAG http version and status code is valid | |
71 | + CHECK_RESULT_TAG check_http_version_and_status_code(const char *, const size_t); | |
72 | + | |
73 | + //! search uri function | |
74 | + //! @param const char* buffer | |
75 | + //! @param const size_t buffer_len | |
76 | + //! @param size_t& uri offset | |
77 | + //! @param size_t& uri length | |
78 | + //! @return bool find is true. not find is false | |
79 | + bool find_uri(const char *, const size_t, size_t &, size_t &); | |
80 | + | |
81 | + //! search status function | |
82 | + //! @param const char* buffer | |
83 | + //! @param const size_t buffer_len | |
84 | + //! @param size_t& status offset | |
85 | + //! @param size_t& status length | |
86 | + //! @return bool find is true. not find is false | |
87 | + bool find_status_code(const char *, const size_t, size_t &, size_t &); | |
88 | + | |
89 | + //! search http header function | |
90 | + //! @param const char* buffer | |
91 | + //! @param const size_t buffer_len | |
92 | + //! @param const string& header name | |
93 | + //! @param size_t& header offset | |
94 | + //! @param size_t& header length | |
95 | + //! @return bool find is true. not find is false | |
96 | + bool find_http_header(const char *, const size_t, const std::string &, size_t &, size_t &); | |
97 | + | |
98 | + //! search http header Cookie function | |
99 | + //! @param const char* buffer | |
100 | + //! @param const size_t buffer_len | |
101 | + //! @param size_t& header offset | |
102 | + //! @param size_t& header length | |
103 | + //! @return bool find is true. not find is false | |
104 | + bool find_http_header_cookie(const char *, const size_t, size_t &, size_t &); | |
105 | + | |
106 | + //! search http header Content_Length function | |
107 | + //! @param const char* buffer | |
108 | + //! @param const size_t buffer_len | |
109 | + //! @param size_t& header offset | |
110 | + //! @param size_t& header length | |
111 | + //! @return bool find is true. not find is false | |
112 | + bool find_http_header_content_length(const char *, const size_t, size_t &, size_t &); | |
113 | + | |
114 | + //! search http header X_Forwarded_For function | |
115 | + //! @param const char* buffer | |
116 | + //! @param const size_t buffer_len | |
117 | + //! @param size_t& header offset | |
118 | + //! @param size_t& header length | |
119 | + //! @return bool find is true. not find is false | |
120 | + bool find_http_header_x_forwarded_for(const char *, const size_t, size_t &, size_t &); | |
121 | + | |
122 | + //! search http header all function | |
123 | + //! @param const char* buffer | |
124 | + //! @param const size_t buffer_len | |
125 | + //! @param size_t& header offset | |
126 | + //! @param size_t& header length | |
127 | + //! @return bool find is true. not find is false | |
128 | + bool find_http_header_all(const char *, const size_t, size_t &, size_t &); | |
129 | + | |
130 | + //! check http get method | |
131 | + //! @param const char* buffer | |
132 | + //! @return bool get method is true. other is false | |
133 | + bool is_get_request(const char *buffer); | |
134 | + | |
135 | + //! check http post method | |
136 | + //! @param const char* buffer | |
137 | + //! @return bool post method is true. other is false | |
138 | + bool is_post_request(const char *buffer); | |
139 | + | |
140 | + //! increment http statistics | |
141 | + //! @param const char* buffer | |
142 | + void increment_stats(const char *buffer); | |
143 | + | |
144 | + //! http statistic information | |
145 | + http_stats http_stats_info; | |
146 | + | |
147 | +public: | |
148 | + | |
149 | + //! constructor | |
150 | + http_protocol_module_base(std::string in_modulename) : protocol_module_base(in_modulename) {}; | |
151 | + | |
152 | + //! destructor | |
153 | + virtual ~http_protocol_module_base() {}; | |
154 | + | |
155 | + //! get base statistic object. | |
156 | + //! @return base statistic object. | |
157 | + stats_base &get_stats() { | |
158 | + return http_stats_info; | |
159 | + } | |
160 | +}; | |
161 | + | |
162 | +} // namespace l7vsd | |
163 | + | |
164 | +#endif //HTTP_PROTOCOL_MODULE_BASE_H |
@@ -0,0 +1,2741 @@ | ||
1 | +/* | |
2 | + * @file protocol_module_simple.cpp | |
3 | + * @brief protocol module of any protocol. | |
4 | + * @brief this module never keep session persistence. | |
5 | + * | |
6 | + * L7VSD: Linux Virtual Server for Layer7 Load Balancing | |
7 | + * Copyright (C) 2009 NTT COMWARE Corporation. | |
8 | + * | |
9 | + * This program is free software; you can redistribute it and/or | |
10 | + * modify it under the terms of the GNU Lesser General Public | |
11 | + * License as published by the Free Software Foundation; either | |
12 | + * version 2.1 of the License, or (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | + * Lesser General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU Lesser General Public | |
20 | + * License along with this library; if not, write to the Free Software | |
21 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |
22 | + * 02110-1301 USA | |
23 | + * | |
24 | + **********************************************************************/ | |
25 | +#include <boost/xpressive/xpressive.hpp> | |
26 | +#include <vector> | |
27 | +#include <list> | |
28 | +#include <algorithm> | |
29 | +#include <iostream> | |
30 | +#include <boost/asio/ip/tcp.hpp> | |
31 | +#include <boost/format.hpp> | |
32 | +#include "protocol_module_simple.h" | |
33 | +#include "utility.h" | |
34 | + | |
35 | +namespace l7vs | |
36 | +{ | |
37 | +const std::string protocol_module_simple::MODULE_NAME = "simple"; | |
38 | +const int protocol_module_simple::THREAD_DIVISION_UP_STREAM = 0; | |
39 | +const int protocol_module_simple::THREAD_DIVISION_DOWN_STREAM = 1; | |
40 | + | |
41 | +const int protocol_module_simple::END_FLAG_OFF = 0; | |
42 | +const int protocol_module_simple::END_FLAG_ON = 1; | |
43 | + | |
44 | +const int protocol_module_simple::ACCEPT_END_FLAG_OFF = 0; | |
45 | +const int protocol_module_simple::ACCEPT_END_FLAG_ON = 1; | |
46 | + | |
47 | +const int protocol_module_simple::SORRY_FLAG_ON = 1; | |
48 | +const int protocol_module_simple::SORRY_FLAG_OFF = 0; | |
49 | + | |
50 | +const int protocol_module_simple::SORRYSERVER_SWITCH_FLAG_OFF = 0; | |
51 | +const int protocol_module_simple::SORRYSERVER_SWITCH_FLAG_ON = 1; | |
52 | + | |
53 | +const int protocol_module_simple::REALSERVER_SWITCH_FLAG_OFF = 0; | |
54 | +const int protocol_module_simple::REALSERVER_SWITCH_FLAG_ON = 1; | |
55 | + | |
56 | +const int protocol_module_simple::EDIT_DIVISION_NO_EDIT = 0; | |
57 | +const int protocol_module_simple::EDIT_DIVISION_EDIT = 1; | |
58 | + | |
59 | +const int protocol_module_simple::FORWARDED_FOR_OFF = 0; | |
60 | +const int protocol_module_simple::FORWARDED_FOR_ON = 1; | |
61 | + | |
62 | +const int protocol_module_simple::COLLECT_STATS_OFF = 0; | |
63 | +const int protocol_module_simple::COLLECT_STATS_ON = 1; | |
64 | + | |
65 | +//! constructor | |
66 | +protocol_module_simple::protocol_module_simple() : | |
67 | + http_protocol_module_base(MODULE_NAME), forwarded_for(FORWARDED_FOR_OFF) | |
68 | +{ | |
69 | + sorry_uri.assign('\0'); | |
70 | + sorry_uri[0] = '/'; | |
71 | +} | |
72 | +//! destructor | |
73 | +protocol_module_simple::~protocol_module_simple() | |
74 | +{ | |
75 | +} | |
76 | +//! tcp protocol support check | |
77 | +//! @return tcp support is true | |
78 | +//! @return tcp not-support is false | |
79 | +bool protocol_module_simple::is_tcp() | |
80 | +{ | |
81 | + return true; | |
82 | +} | |
83 | + | |
84 | +//! udp protocol support check | |
85 | +//! @return udp support is true | |
86 | +//! @return udp not-support is false | |
87 | +bool protocol_module_simple::is_udp() | |
88 | +{ | |
89 | + return false; | |
90 | +} | |
91 | + | |
92 | +//! replication interval interrupt | |
93 | +//! timer thread call this function. from virtualservice. | |
94 | +void protocol_module_simple::replication_interrupt() | |
95 | +{ | |
96 | +} | |
97 | +//! initialize function. called from module control. module loaded call | |
98 | +//! @param[in] realserver list iterator begin function object type | |
99 | +//! @param[in] realserver list iterator end function object type | |
100 | +//! @param[in] realserver list iterator next function object type | |
101 | +//! @param[in] realserver list mutex lock function object type. | |
102 | +//! @param[in] realserver list mutex unlock function object type | |
103 | +void protocol_module_simple::initialize(rs_list_itr_func_type inlist_begin, | |
104 | + rs_list_itr_func_type inlist_end, | |
105 | + rs_list_itr_next_func_type inlist_next, | |
106 | + boost::function< void(void) > inlist_lock, | |
107 | + boost::function< void(void) > inlist_unlock) | |
108 | +{ | |
109 | + //RealServer list begin function | |
110 | + rs_list_begin = inlist_begin; | |
111 | + //RealServer list end function | |
112 | + rs_list_end = inlist_end; | |
113 | + //RealServer list next function | |
114 | + rs_list_next = inlist_next; | |
115 | + //RealServer list lock function | |
116 | + rs_list_lock = inlist_lock; | |
117 | + //RealServer list unlock function | |
118 | + rs_list_unlock = inlist_unlock; | |
119 | +} | |
120 | + | |
121 | +//! finalize called from module control. module unloaded call. | |
122 | +void protocol_module_simple::finalize() | |
123 | +{ | |
124 | + //RealServer list functions initialization | |
125 | + //RealServer list begin function | |
126 | + rs_list_begin.clear(); | |
127 | + //RealServer list end function | |
128 | + rs_list_end.clear(); | |
129 | + //RealServer list next function | |
130 | + rs_list_next.clear(); | |
131 | + //RealServer list lock function | |
132 | + rs_list_lock.clear(); | |
133 | + //RealServer list unlock function | |
134 | + rs_list_unlock.clear(); | |
135 | + | |
136 | + //Replication functions initialization | |
137 | + //component memory allocate function | |
138 | + replication_pay_memory.clear(); | |
139 | + //component memory lock function | |
140 | + replication_area_lock.clear(); | |
141 | + //component memory unlock function | |
142 | + replication_area_unlock.clear(); | |
143 | + | |
144 | + //ScheduleModule's functions initialization | |
145 | + schedule_tcp.clear(); | |
146 | + | |
147 | + //logger functions initialization | |
148 | + //log level getting function | |
149 | + getloglevel.clear(); | |
150 | + //logger(Fatal) | |
151 | + putLogFatal.clear(); | |
152 | + //logger(Error) | |
153 | + putLogError.clear(); | |
154 | + //logger(Warn) | |
155 | + putLogWarn.clear(); | |
156 | + //logger(Info) | |
157 | + putLogInfo.clear(); | |
158 | + //logger(Debug) | |
159 | + putLogDebug.clear(); | |
160 | +} | |
161 | + | |
162 | +//! sorry support check | |
163 | +//! @return true sorry mode is supported. | |
164 | +//! @return false sorry mode is unsupported. | |
165 | +bool protocol_module_simple::is_use_sorry() | |
166 | +{ | |
167 | + return true; | |
168 | +} | |
169 | + | |
170 | +//! realserver list update event | |
171 | +void protocol_module_simple::handle_rslist_update() | |
172 | +{ | |
173 | +} | |
174 | + | |
175 | +//! module parameter check.used by l7vsadm | |
176 | +//! @param[in] module parameter string list | |
177 | +//! @return result.flag true is parameter is no problem. | |
178 | +//! @return result.flag false is parameter is problem. | |
179 | +protocol_module_base::check_message_result protocol_module_simple::check_parameter(const std::vector < | |
180 | + std::string > & args) | |
181 | +{ | |
182 | + using namespace boost::xpressive; | |
183 | + //set check result true | |
184 | + check_message_result check_result; | |
185 | + check_result.flag = true; | |
186 | + | |
187 | + typedef std::vector<std::string>::const_iterator vec_str_it; | |
188 | + | |
189 | + try { | |
190 | + vec_str_it it = args.begin(); | |
191 | + vec_str_it it_end = args.end(); | |
192 | + //loop option strings | |
193 | + for (; it != it_end; ++it) { | |
194 | + //set check result flag false | |
195 | + check_result.flag = false; | |
196 | + //set check result message | |
197 | + check_result.message = "Option error."; | |
198 | + putLogError(100005, check_result.message, __FILE__, __LINE__); | |
199 | + //loop break | |
200 | + break; | |
201 | + } | |
202 | + } catch (...) { | |
203 | + check_result.flag = false; | |
204 | + } | |
205 | + | |
206 | + return check_result; | |
207 | +} | |
208 | + | |
209 | +//! parameter set | |
210 | +//! @param[in] module parameter string list | |
211 | +//! @return result.flag true is parameter is no problem. | |
212 | +//! @return result.flag false is parameter is problem. | |
213 | +protocol_module_base::check_message_result protocol_module_simple::set_parameter(const std::vector < | |
214 | + std::string > & args) | |
215 | +{ | |
216 | + using namespace boost::xpressive; | |
217 | + //set check result flag true | |
218 | + check_message_result check_result; | |
219 | + check_result.flag = true; | |
220 | + | |
221 | + typedef std::vector<std::string>::const_iterator vec_str_it; | |
222 | + | |
223 | + try { | |
224 | + vec_str_it it = args.begin(); | |
225 | + vec_str_it it_end = args.end(); | |
226 | + for (; it != it_end; ++it) { | |
227 | + //set check result flag false | |
228 | + check_result.flag = false; | |
229 | + //set check result message | |
230 | + check_result.message = "Option error."; | |
231 | + | |
232 | + putLogError(100013, check_result.message, __FILE__, | |
233 | + __LINE__); | |
234 | + | |
235 | + break; | |
236 | + } | |
237 | + } catch (...) { | |
238 | + check_result.flag = false; | |
239 | + } | |
240 | + | |
241 | + return check_result; | |
242 | +} | |
243 | + | |
244 | +//! parameter add | |
245 | +//! @param[in] module parameter string list | |
246 | +//! @return result.flag true is parameter is no problem. | |
247 | +//! @return result.flag false is parameter is problem. | |
248 | +protocol_module_base::check_message_result protocol_module_simple::add_parameter(const std::vector < | |
249 | + std::string > & args) | |
250 | +{ | |
251 | + check_message_result check_result; | |
252 | + //set check result flag true | |
253 | + check_result.flag = true; | |
254 | + | |
255 | + //param list is not empty | |
256 | + if (!args.empty()) { | |
257 | + //set check result flag false | |
258 | + check_result.flag = false; | |
259 | + //set check result message | |
260 | + check_result.message = "Cannot add option."; | |
261 | + putLogError(100016, check_result.message, __FILE__, __LINE__); | |
262 | + } | |
263 | + | |
264 | + return check_result; | |
265 | +} | |
266 | + | |
267 | +//! get option info | |
268 | +//! @param[out] module parameter string | |
269 | +void protocol_module_simple::get_option_info(std::string &option) | |
270 | +{ | |
271 | +} | |
272 | + | |
273 | +//! TCP/IP scheduled function registration. | |
274 | +//! @param[in] schedule module TCP/IP scheduled function object type | |
275 | +void protocol_module_simple::register_schedule(tcp_schedule_func_type inschedule) | |
276 | +{ | |
277 | + schedule_tcp = inschedule; | |
278 | +} | |
279 | + | |
280 | +//! UDP scheduled function registration | |
281 | +//! @param[in] schedule module UDP scheduled function object type | |
282 | +void protocol_module_simple::register_schedule(udp_schedule_func_type inschedule) | |
283 | +{ | |
284 | +} | |
285 | + | |
286 | +//! called from session initialize use in upstream_thread | |
287 | +//! @param[in] upstream thread id. | |
288 | +//! @param[in] downstream thread id | |
289 | +//! @return session use EVENT mode. | |
290 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_session_initialize( | |
291 | + const boost::thread::id up_thread_id, const boost::thread::id down_thread_id, | |
292 | + const boost::asio::ip::tcp::endpoint &client_endpoint_tcp, | |
293 | + const boost::asio::ip::udp::endpoint &client_endpoint_udp) | |
294 | +{ | |
295 | + EVENT_TAG status = FINALIZE; | |
296 | + | |
297 | + //session thread initialization | |
298 | + try { | |
299 | + thread_data_ptr p_up(new session_thread_data_simple); | |
300 | + p_up->thread_id = up_thread_id; | |
301 | + p_up->thread_division = THREAD_DIVISION_UP_STREAM; | |
302 | + p_up->pair_thread_id = down_thread_id; | |
303 | + p_up->accept_end_flag = ACCEPT_END_FLAG_OFF; | |
304 | + p_up->end_flag = END_FLAG_OFF; | |
305 | + p_up->sorry_flag = SORRY_FLAG_OFF; | |
306 | + p_up->sorryserver_switch_flag = SORRYSERVER_SWITCH_FLAG_OFF; | |
307 | + p_up->realserver_switch_flag = REALSERVER_SWITCH_FLAG_OFF; | |
308 | + p_up->last_status = INITIALIZE; | |
309 | + p_up->client_endpoint_tcp = client_endpoint_tcp; | |
310 | + | |
311 | + receive_data recv_data; | |
312 | + p_up->receive_data_map[client_endpoint_tcp] = recv_data; | |
313 | + | |
314 | + thread_data_ptr p_down(new session_thread_data_simple); | |
315 | + p_down->thread_id = down_thread_id; | |
316 | + p_down->thread_division = THREAD_DIVISION_DOWN_STREAM; | |
317 | + p_down->pair_thread_id = up_thread_id; | |
318 | + p_down->accept_end_flag = ACCEPT_END_FLAG_OFF; | |
319 | + p_down->end_flag = END_FLAG_OFF; | |
320 | + p_down->sorry_flag = SORRY_FLAG_OFF; | |
321 | + p_down->sorryserver_switch_flag = SORRYSERVER_SWITCH_FLAG_OFF; | |
322 | + p_down->realserver_switch_flag = REALSERVER_SWITCH_FLAG_OFF; | |
323 | + p_down->last_status = INITIALIZE; | |
324 | + p_down->client_endpoint_tcp = client_endpoint_tcp; | |
325 | + | |
326 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
327 | + | |
328 | + session_thread_data_map[up_thread_id] = p_up; | |
329 | + session_thread_data_map[down_thread_id] = p_down; | |
330 | + | |
331 | + status = ACCEPT; | |
332 | + } catch (...) { | |
333 | + status = FINALIZE; | |
334 | + } | |
335 | + | |
336 | + return status; | |
337 | +} | |
338 | +//! called from session finalize use in upstream thread. | |
339 | +//! @param[in] upstream thread id. | |
340 | +//! @param[in] downstream thread id | |
341 | +//! @return session use EVENT mode. | |
342 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_session_finalize( | |
343 | + const boost::thread::id up_thread_id, const boost::thread::id down_thread_id) | |
344 | +{ | |
345 | + EVENT_TAG status = STOP; | |
346 | + | |
347 | + //session thread free | |
348 | + try { | |
349 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
350 | + | |
351 | + session_thread_data_map_it session_thread_data_it = session_thread_data_map.find(up_thread_id); | |
352 | + if (session_thread_data_it != session_thread_data_map.end()) { | |
353 | + thread_data_ptr p_up = session_thread_data_it->second; | |
354 | + session_thread_data_map.erase(up_thread_id); | |
355 | + } | |
356 | + | |
357 | + session_thread_data_it = session_thread_data_map.find(down_thread_id); | |
358 | + if (session_thread_data_it != session_thread_data_map.end()) { | |
359 | + thread_data_ptr p_down = session_thread_data_it->second; | |
360 | + session_thread_data_map.erase(down_thread_id); | |
361 | + } | |
362 | + | |
363 | + status = STOP; | |
364 | + } catch (...) { | |
365 | + status = STOP; | |
366 | + } | |
367 | + | |
368 | + return status; | |
369 | +} | |
370 | + | |
371 | +//! called from after session accept.in client socket use in upstream thread. | |
372 | +//! @param[in] upstream thread id. | |
373 | +//! @return session use EVENT mode. | |
374 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_accept(const boost::thread::id thread_id) | |
375 | +{ | |
376 | + EVENT_TAG status = FINALIZE; | |
377 | + thread_data_ptr session_data; | |
378 | + session_thread_data_map_it session_thread_it; | |
379 | + | |
380 | + try { | |
381 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
382 | + | |
383 | + session_thread_it = session_thread_data_map.find(thread_id); | |
384 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
385 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
386 | + formatter % boost::this_thread::get_id(); | |
387 | + putLogError(100022, formatter.str(), __FILE__, __LINE__); | |
388 | + throw - 1; | |
389 | + } | |
390 | + | |
391 | + session_data = session_thread_it->second; | |
392 | + | |
393 | + //set accept end flag ON | |
394 | + session_data->accept_end_flag = ACCEPT_END_FLAG_ON; | |
395 | + | |
396 | + //sorry flag on | |
397 | + if (session_data->sorry_flag == SORRY_FLAG_ON) { | |
398 | + //set return status | |
399 | + status = SORRYSERVER_SELECT; | |
400 | + } | |
401 | + //sorry flag off | |
402 | + else { | |
403 | + //set return status | |
404 | + status = REALSERVER_SELECT; | |
405 | + } | |
406 | + } catch (...) { | |
407 | + status = FINALIZE; | |
408 | + } | |
409 | + | |
410 | + return status; | |
411 | +} | |
412 | + | |
413 | +//! called from after session recv in client socket. use in upstream thread. | |
414 | +//! @param[in] upstream thread id | |
415 | +//! @param[in] receive buffer reference. | |
416 | +//! @param[in] receive length | |
417 | +//! @return session use EVENT mode. | |
418 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_client_recv(const boost::thread::id thread_id, | |
419 | + const boost::array<char, MAX_BUFFER_SIZE>& recvbuffer, const size_t recvlen) | |
420 | +{ | |
421 | + EVENT_TAG status = FINALIZE; | |
422 | + size_t data_remain_start = 0; | |
423 | + size_t data_remain_size = 0; | |
424 | + size_t request_data_remain_size = 0; | |
425 | + size_t buffer_size = 0; | |
426 | + std::string str_value; | |
427 | + thread_data_ptr session_data; | |
428 | + char *buffer1 = NULL; | |
429 | + char *buffer2 = NULL; | |
430 | + session_thread_data_map_it session_thread_it; | |
431 | + receive_data_map_it receive_data_it; | |
432 | + | |
433 | + // hibari add for debug | |
434 | + boost::format formatter("handle_client_recv() => recvbuffer = %s"); | |
435 | + formatter % recvbuffer.data() ; | |
436 | + putLogFatal(9999, formatter.str(), __FILE__, __LINE__); | |
437 | + // hibari add end | |
438 | + | |
439 | + | |
440 | + //parameter check | |
441 | + if (recvlen > recvbuffer.size()) { | |
442 | + std::cerr << "protocol_module_simple::handle_client_recv() : Data size bigger than buffer size." << std::endl; | |
443 | + boost::format formatter("Data size bigger than buffer size. thread id : %d."); | |
444 | + formatter % boost::this_thread::get_id(); | |
445 | + putLogError(100025, formatter.str(), __FILE__, __LINE__); | |
446 | + return FINALIZE; | |
447 | + } | |
448 | + | |
449 | + try { | |
450 | + { | |
451 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
452 | + | |
453 | + session_thread_it = session_thread_data_map.find(thread_id); | |
454 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
455 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
456 | + formatter % boost::this_thread::get_id(); | |
457 | + putLogError(100026, formatter.str(), __FILE__, __LINE__); | |
458 | + throw - 1; | |
459 | + } | |
460 | + | |
461 | + session_data = session_thread_it->second; | |
462 | + } | |
463 | + | |
464 | + //end flag on | |
465 | + if (session_data->end_flag == END_FLAG_ON) { | |
466 | + status = CLIENT_RECV; | |
467 | + } | |
468 | + //end flag off | |
469 | + else { | |
470 | + receive_data_it = session_data->receive_data_map.find(session_data->client_endpoint_tcp); | |
471 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
472 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
473 | + formatter % boost::this_thread::get_id(); | |
474 | + putLogError(100027, formatter.str(), __FILE__, __LINE__); | |
475 | + throw - 1; | |
476 | + } | |
477 | + | |
478 | + receive_data &recv_data = receive_data_it->second; | |
479 | + | |
480 | + send_status_it it = recv_data.send_status_list.begin(); | |
481 | + send_status_it it_end = recv_data.send_status_list.end(); | |
482 | + | |
483 | + //status list check | |
484 | + it = std::find_if(it, it_end, data_send_ok()); | |
485 | + if (unlikely(it != it_end)) { | |
486 | + boost::format formatter("Sending data is not correct. thread id : %d."); | |
487 | + formatter % boost::this_thread::get_id(); | |
488 | + putLogError(100028, formatter.str(), __FILE__, __LINE__); | |
489 | + throw - 1; | |
490 | + } | |
491 | + | |
492 | + //status list check | |
493 | + it = recv_data.send_status_list.begin(); | |
494 | + it = std::adjacent_find(it, it_end, data_send_repeated()); | |
495 | + if (unlikely(it != it_end)) { | |
496 | + boost::format formatter("Sending data is not correct. thread id : %d."); | |
497 | + formatter % boost::this_thread::get_id(); | |
498 | + putLogError(100029, formatter.str(), __FILE__, __LINE__); | |
499 | + throw - 1; | |
500 | + } | |
501 | + | |
502 | + it = recv_data.send_status_list.begin(); | |
503 | + //get original status info | |
504 | + while (it != it_end) { | |
505 | + //item status is SEND_END | |
506 | + if (it->status == SEND_END) { | |
507 | + //erase from list | |
508 | + recv_data.send_status_list.erase(it++); | |
509 | + continue; | |
510 | + } | |
511 | + //item status is SEND_CONTINUE | |
512 | + else if (it->status == SEND_CONTINUE) { | |
513 | + it->send_offset += it->send_end_size; | |
514 | + data_remain_start = it->send_offset; | |
515 | + break; | |
516 | + } | |
517 | + //item status is SEND_NG | |
518 | + else { | |
519 | + data_remain_start = it->send_offset; | |
520 | + data_remain_size = it->unsend_size; | |
521 | + break; | |
522 | + } | |
523 | + | |
524 | + ++it; | |
525 | + } | |
526 | + | |
527 | + //receive buffer process | |
528 | + //buffer rest size < request size | |
529 | + if (recv_data.receive_buffer_rest_size < recvlen) { | |
530 | + //buffer max size < remain size + request size | |
531 | + //buffer is need reallocate | |
532 | + if (recv_data.receive_buffer_max_size < data_remain_size + recvlen) { | |
533 | + //the buffer's size that will be allocated is exceed the upper limit value | |
534 | + if (MAX_SIMPLE_MODULE_BUFFER_SIZE < data_remain_size + recvlen) { | |
535 | + std::cerr << "protocol_module_simple::handle_client_recv() : the buffer's size that will be allocated is exceed the upper limit value." << std::endl; | |
536 | + boost::format formatter("The buffer's size that will be allocated is exceed the upper limit value. thread id : %d."); | |
537 | + formatter % boost::this_thread::get_id(); | |
538 | + putLogError(100030, formatter.str(), __FILE__, __LINE__); | |
539 | + return FINALIZE; | |
540 | + } | |
541 | + | |
542 | + buffer_size = (data_remain_size + recvlen) > MAX_BUFFER_SIZE ? (data_remain_size + recvlen) : MAX_BUFFER_SIZE; | |
543 | + //receive_buffer1's memory allocate and initialization | |
544 | + buffer1 = new char[buffer_size]; | |
545 | + memset(buffer1, 0, buffer_size); | |
546 | + //receive_buffer2's memory allocate and initialization | |
547 | + buffer2 = new char[buffer_size]; | |
548 | + memset(buffer2, 0, buffer_size); | |
549 | + | |
550 | + //copy data from old buffer to new buffer | |
551 | + memcpy(buffer1, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
552 | + memcpy(buffer1 + data_remain_size, recvbuffer.data(), recvlen); | |
553 | + //free old buffer1 and old buffer2 | |
554 | + if (recv_data.receive_buffer1 != NULL) { | |
555 | + delete[] recv_data.receive_buffer1; | |
556 | + recv_data.receive_buffer1 = NULL; | |
557 | + } | |
558 | + | |
559 | + if (recv_data.receive_buffer2 != NULL) { | |
560 | + delete[] recv_data.receive_buffer2; | |
561 | + recv_data.receive_buffer2 = NULL; | |
562 | + } | |
563 | + | |
564 | + //set new buffer pointer | |
565 | + recv_data.receive_buffer1 = buffer1; | |
566 | + recv_data.receive_buffer2 = buffer2; | |
567 | + recv_data.receive_buffer = recv_data.receive_buffer1; | |
568 | + //set new buffer's max size | |
569 | + recv_data.receive_buffer_max_size = buffer_size; | |
570 | + } | |
571 | + //buffer's max size >= remain data size + request size | |
572 | + //buffer isn't need reallocate, but switch | |
573 | + else { | |
574 | + //pointer valid check | |
575 | + if (unlikely(recv_data.receive_buffer1 == NULL || recv_data.receive_buffer2 == NULL)) { | |
576 | + boost::format formatter("Invalid pointer. thread id : %d."); | |
577 | + formatter % boost::this_thread::get_id(); | |
578 | + putLogError(100031, formatter.str(), __FILE__, __LINE__); | |
579 | + throw - 1; | |
580 | + } | |
581 | + //using buffer is buffer1 | |
582 | + if (recv_data.receive_buffer == recv_data.receive_buffer1) { | |
583 | + //buffer2 initialization | |
584 | + memset(recv_data.receive_buffer2, 0, recv_data.receive_buffer_max_size); | |
585 | + //copy data from buffer1 to buffer2 | |
586 | + memcpy(recv_data.receive_buffer2, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
587 | + memcpy(recv_data.receive_buffer2 + data_remain_size, recvbuffer.data(), recvlen); | |
588 | + //set buffer2 as using buffer | |
589 | + recv_data.receive_buffer = recv_data.receive_buffer2; | |
590 | + } | |
591 | + //using buffer is buffer2 | |
592 | + else { | |
593 | + //buffer1 initialization | |
594 | + memset(recv_data.receive_buffer1, 0, recv_data.receive_buffer_max_size); | |
595 | + //copy data from buffer2 to buffer1 | |
596 | + memcpy(recv_data.receive_buffer1, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
597 | + memcpy(recv_data.receive_buffer1 + data_remain_size, recvbuffer.data(), recvlen); | |
598 | + //set buffer1 as using buffer | |
599 | + recv_data.receive_buffer = recv_data.receive_buffer1; | |
600 | + } | |
601 | + } | |
602 | + | |
603 | + //set buffer's rest size | |
604 | + recv_data.receive_buffer_rest_size = recv_data.receive_buffer_max_size - data_remain_size - recvlen; | |
605 | + | |
606 | + //remain_size recalc | |
607 | + data_remain_size += recvlen; | |
608 | + | |
609 | + send_status_it it_begin = recv_data.send_status_list.begin(); | |
610 | + send_status_it it_end = recv_data.send_status_list.end(); | |
611 | + | |
612 | + //offset recalc | |
613 | + for (; it_begin != it_end; ++it_begin) { | |
614 | + it_begin->send_offset -= data_remain_start; | |
615 | + } | |
616 | + } | |
617 | + //buffer's rest size >= request size | |
618 | + else { | |
619 | + //pointer valid check | |
620 | + if (unlikely(recv_data.receive_buffer == NULL)) { | |
621 | + boost::format formatter("Invalid pointer. thread id : %d."); | |
622 | + formatter % boost::this_thread::get_id(); | |
623 | + putLogError(100032, formatter.str(), __FILE__, __LINE__); | |
624 | + throw - 1; | |
625 | + } | |
626 | + //copy data from parameter to using buffer | |
627 | + memcpy(recv_data.receive_buffer + recv_data.receive_buffer_max_size - recv_data.receive_buffer_rest_size, | |
628 | + recvbuffer.data(), recvlen); | |
629 | + //buffer's rest size recalc | |
630 | + recv_data.receive_buffer_rest_size -= recvlen; | |
631 | + //remain data size recalc | |
632 | + data_remain_size += recvlen; | |
633 | + } | |
634 | + | |
635 | + it = recv_data.send_status_list.begin(); | |
636 | + it_end = recv_data.send_status_list.end(); | |
637 | + | |
638 | + //set request rest size | |
639 | + request_data_remain_size = recvlen; | |
640 | + | |
641 | + //original status process | |
642 | + for (; it != it_end; ++it) { | |
643 | + //status is SEND_CONTINUE | |
644 | + if (it->status == SEND_CONTINUE) { | |
645 | + //send rest size > request size | |
646 | + if (it->send_rest_size > request_data_remain_size) { | |
647 | + //send possible size recalc | |
648 | + it->send_possible_size = request_data_remain_size; | |
649 | + //send rest size recalc | |
650 | + it->send_rest_size -= request_data_remain_size; | |
651 | + //send end size recalc | |
652 | + it->send_end_size = 0; | |
653 | + //request size recalc | |
654 | + request_data_remain_size = 0; | |
655 | + } | |
656 | + //send rest size <= request size | |
657 | + else { | |
658 | + //send possible size recalc | |
659 | + it->send_possible_size = it->send_rest_size; | |
660 | + //send rest size recalc | |
661 | + request_data_remain_size -= it->send_rest_size; | |
662 | + //send end size recalc | |
663 | + it->send_end_size = 0; | |
664 | + //request size recalc | |
665 | + it->send_rest_size = 0; | |
666 | + } | |
667 | + //set edit_division flag off | |
668 | + it->edit_division = EDIT_DIVISION_NO_EDIT; | |
669 | + //set status SEND_OK | |
670 | + it->status = SEND_OK; | |
671 | + } | |
672 | + //status is SEND_NG | |
673 | + else if (it->status == SEND_NG) { | |
674 | + //set edit_division flag off | |
675 | + it->edit_division = EDIT_DIVISION_NO_EDIT; | |
676 | + //send_rest_size recalc | |
677 | + it->send_rest_size = it->unsend_size + request_data_remain_size; | |
678 | + | |
679 | + //recalc fields value according to send_rest_size and request rest size | |
680 | + if (it->send_rest_size > it->unsend_size + request_data_remain_size) { | |
681 | + it->send_possible_size = it->unsend_size + request_data_remain_size; | |
682 | + it->send_rest_size -= (it->unsend_size + request_data_remain_size); | |
683 | + it->send_end_size = 0; | |
684 | + it->unsend_size = 0; | |
685 | + request_data_remain_size = 0; | |
686 | + } else { | |
687 | + it->send_possible_size = it->send_rest_size; | |
688 | + request_data_remain_size = it->unsend_size + request_data_remain_size - it->send_rest_size; | |
689 | + it->send_end_size = 0; | |
690 | + it->unsend_size = 0; | |
691 | + it->send_rest_size = 0; | |
692 | + } | |
693 | + | |
694 | + //change status from SEND_NG to SEND_OK | |
695 | + it->status = SEND_OK; | |
696 | + } | |
697 | + //no request rest data to process | |
698 | + if (request_data_remain_size <= 0) { | |
699 | + break; | |
700 | + } | |
701 | + } | |
702 | + //there are still rest data need to process | |
703 | + //new status created and add to status list | |
704 | + while (request_data_remain_size > 0) { | |
705 | + //new status created | |
706 | + send_status new_send_state; | |
707 | + | |
708 | + new_send_state.edit_division = EDIT_DIVISION_NO_EDIT; | |
709 | + new_send_state.send_end_size = 0; | |
710 | + new_send_state.send_offset = 0; | |
711 | + new_send_state.send_possible_size = 0; | |
712 | + new_send_state.unsend_size = 0; | |
713 | + new_send_state.send_rest_size = 0; | |
714 | + //status initialize to SEND_NG | |
715 | + new_send_state.status = SEND_NG; | |
716 | + //add new status to status_list | |
717 | + recv_data.send_status_list.push_back(new_send_state); | |
718 | + std::list<send_status>::reverse_iterator new_send_it = recv_data.send_status_list.rbegin(); | |
719 | + //calc offset | |
720 | + new_send_it->send_offset = recv_data.receive_buffer_max_size - recv_data.receive_buffer_rest_size | |
721 | + - request_data_remain_size; | |
722 | + | |
723 | + new_send_it->edit_division = EDIT_DIVISION_NO_EDIT; | |
724 | + new_send_it->send_rest_size = request_data_remain_size; | |
725 | + | |
726 | + //recalc fields value according to send_rest_size and request rest size | |
727 | + if (new_send_it->send_rest_size > request_data_remain_size) { | |
728 | + new_send_it->send_possible_size = request_data_remain_size; | |
729 | + new_send_it->send_rest_size -= request_data_remain_size; | |
730 | + new_send_it->send_end_size = 0; | |
731 | + request_data_remain_size = 0; | |
732 | + } else { | |
733 | + new_send_it->send_possible_size = new_send_it->send_rest_size; | |
734 | + request_data_remain_size -= new_send_it->send_rest_size; | |
735 | + new_send_it->send_end_size = 0; | |
736 | + new_send_it->send_rest_size = 0; | |
737 | + } | |
738 | + | |
739 | + //change status from SEND_NG to SEND_OK | |
740 | + new_send_it->status = SEND_OK; | |
741 | + } | |
742 | + | |
743 | + //search for send_possible item in status list | |
744 | + send_status_it it_find = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), | |
745 | + data_send_possible()); | |
746 | + //the data that can be sent possible is exist | |
747 | + if (it_find != recv_data.send_status_list.end()) { | |
748 | + //sorry flag is on | |
749 | + if (session_data->sorry_flag == SORRY_FLAG_ON) { | |
750 | + status = SORRYSERVER_CONNECT; | |
751 | + } | |
752 | + //sorry flag is off | |
753 | + else { | |
754 | + status = REALSERVER_CONNECT; | |
755 | + } | |
756 | + } | |
757 | + //the data that can be sent possible is not exist | |
758 | + else { | |
759 | + status = CLIENT_RECV; | |
760 | + } | |
761 | + } | |
762 | + } catch (...) { | |
763 | + status = FINALIZE; | |
764 | + } | |
765 | + | |
766 | + return status; | |
767 | +} | |
768 | + | |
769 | +//! called from after realserver select.use in upstream thread. | |
770 | +//! @param[in] upstream thread id | |
771 | +//! @param[out] realserver TCP endpoint | |
772 | +//! @return session use EVENT mode. | |
773 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_select( | |
774 | + const boost::thread::id thread_id, boost::asio::ip::tcp::endpoint &rs_endpoint) | |
775 | +{ | |
776 | + EVENT_TAG status = FINALIZE; | |
777 | + boost::asio::ip::tcp::endpoint tmp_endpoint; | |
778 | + thread_data_ptr session_data; | |
779 | + session_thread_data_map_it session_thread_it; | |
780 | + session_thread_data_map_it session_thread_it_end; | |
781 | + receive_data_map_it receive_data_it; | |
782 | + | |
783 | + if (schedule_tcp.empty()) { | |
784 | + std::cerr << "protocol_module_simple::handle_realserver_select() : Schedule_tcp function is empty." << std::endl; | |
785 | + boost::format formatter("Schedule_tcp function is empty. thread id : %d."); | |
786 | + formatter % boost::this_thread::get_id(); | |
787 | + putLogError(100037, formatter.str(), __FILE__, __LINE__); | |
788 | + return FINALIZE; | |
789 | + } | |
790 | + | |
791 | + try { | |
792 | + { | |
793 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
794 | + | |
795 | + session_thread_it = session_thread_data_map.find(thread_id); | |
796 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
797 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
798 | + formatter % boost::this_thread::get_id(); | |
799 | + putLogError(100038, formatter.str(), __FILE__, __LINE__); | |
800 | + throw - 1; | |
801 | + } | |
802 | + | |
803 | + session_data = session_thread_it->second; | |
804 | + } | |
805 | + | |
806 | + //call schedule_module's schedule function, get realserver endpoint | |
807 | + { | |
808 | + rs_list_scoped_lock scoped_lock(rs_list_lock, rs_list_unlock); | |
809 | + schedule_tcp(thread_id, rs_list_begin, rs_list_end, rs_list_next, rs_endpoint); | |
810 | + } | |
811 | + | |
812 | + //endpoint decide | |
813 | + if (rs_endpoint != tmp_endpoint) { | |
814 | + //save rs endpoint | |
815 | + session_data->target_endpoint = rs_endpoint; | |
816 | + status = REALSERVER_CONNECT; | |
817 | + } else { | |
818 | + //set end flag on | |
819 | + session_data->sorry_flag = SORRY_FLAG_ON; | |
820 | + status = SORRYSERVER_SELECT; | |
821 | + } | |
822 | + } catch (...) { | |
823 | + status = FINALIZE; | |
824 | + } | |
825 | + | |
826 | + return status; | |
827 | +} | |
828 | + | |
829 | +//! called from after realserver select | |
830 | +//! @param[in] upstream thread id | |
831 | +//! @param[out] realserver UDP endpoint | |
832 | +//! @param[out] sendbuffer reference | |
833 | +//! @param[out] send data length | |
834 | +//! @return session use EVENT mode. | |
835 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_select( | |
836 | + const boost::thread::id thread_id, boost::asio::ip::udp::endpoint &rs_endpoint, boost::array < char, | |
837 | + MAX_BUFFER_SIZE > & sendbuffer, size_t &datalen) | |
838 | +{ | |
839 | + return STOP; | |
840 | +} | |
841 | +//! called from after realserver connect | |
842 | +//! @param[in] upstream thread id | |
843 | +//! @param[out] sendbuffer reference | |
844 | +//! @param[out] send data length | |
845 | +//! @return session use EVENT mode. | |
846 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_connect( | |
847 | + const boost::thread::id thread_id, boost::array<char, MAX_BUFFER_SIZE>& sendbuffer, size_t &datalen) | |
848 | +{ | |
849 | + EVENT_TAG status = FINALIZE; | |
850 | + size_t send_buffer_remian_size = 0; | |
851 | + size_t copy_size = 0; | |
852 | + const int send_buffer_end_size = sendbuffer.max_size(); | |
853 | + thread_data_ptr session_data; | |
854 | + | |
855 | + try { | |
856 | + session_thread_data_map_mutex.lock(); | |
857 | + | |
858 | + //thread id check | |
859 | + session_thread_data_map_it session_thread_it = session_thread_data_map.find(thread_id); | |
860 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
861 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
862 | + formatter % boost::this_thread::get_id(); | |
863 | + putLogError(100042, formatter.str(), __FILE__, __LINE__); | |
864 | + session_thread_data_map_mutex.unlock(); | |
865 | + throw - 1; | |
866 | + } | |
867 | + | |
868 | + session_data = session_thread_it->second; | |
869 | + | |
870 | + //endpoint check | |
871 | + receive_data_map_it receive_data_it = session_data->receive_data_map.find(session_data->client_endpoint_tcp); | |
872 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
873 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
874 | + formatter % boost::this_thread::get_id(); | |
875 | + putLogError(100043, formatter.str(), __FILE__, __LINE__); | |
876 | + session_thread_data_map_mutex.unlock(); | |
877 | + throw - 1; | |
878 | + } | |
879 | + | |
880 | + //receive_buffer pointer check | |
881 | + receive_data &recv_data = receive_data_it->second; | |
882 | + if (unlikely(recv_data.receive_buffer == NULL)) { | |
883 | + session_thread_data_map_mutex.unlock(); | |
884 | + return CLIENT_RECV; | |
885 | + } | |
886 | + | |
887 | + //send list check | |
888 | + send_status_it it = recv_data.send_status_list.begin(); | |
889 | + send_status_it it_end = recv_data.send_status_list.end(); | |
890 | + it = find_if(it, it_end, data_send_possible()); | |
891 | + if (unlikely(it == it_end)) { | |
892 | + boost::format formatter("Sending possible data is not existed. thread id : %d."); | |
893 | + formatter % boost::this_thread::get_id(); | |
894 | + putLogError(100045, formatter.str(), __FILE__, __LINE__); | |
895 | + session_thread_data_map_mutex.unlock(); | |
896 | + throw - 1; | |
897 | + } | |
898 | + session_thread_data_map_mutex.unlock(); | |
899 | + | |
900 | + //send buffer rest size initialization | |
901 | + send_buffer_remian_size = send_buffer_end_size; | |
902 | + | |
903 | + //copy data as large as possible | |
904 | + //send_possible_size is larger | |
905 | + if (send_buffer_remian_size >= it->send_possible_size) { | |
906 | + copy_size = it->send_possible_size; | |
907 | + //copy data by send_possible size | |
908 | + memcpy(sendbuffer.data(), recv_data.receive_buffer + it->send_offset, copy_size); | |
909 | + it->send_end_size = copy_size; | |
910 | + it->send_possible_size = 0; | |
911 | + send_buffer_remian_size -= copy_size; | |
912 | + } | |
913 | + //buffer rest size is larger | |
914 | + else { | |
915 | + //copy data by buffer rest size | |
916 | + memcpy(sendbuffer.data(), recv_data.receive_buffer + it->send_offset, send_buffer_remian_size); | |
917 | + it->send_end_size = send_buffer_remian_size; | |
918 | + it->send_possible_size -= send_buffer_remian_size; | |
919 | + send_buffer_remian_size = 0; | |
920 | + } | |
921 | + | |
922 | + //set copied data length | |
923 | + datalen = send_buffer_end_size - send_buffer_remian_size; | |
924 | + status = REALSERVER_SEND; | |
925 | + } catch (...) { | |
926 | + status = FINALIZE; | |
927 | + } | |
928 | + | |
929 | + return status; | |
930 | +} | |
931 | + | |
932 | +//! called from after realserver connection fail | |
933 | +//! @param[in] upstream thread id | |
934 | +//! @param[in] fail realserver endpoint reference | |
935 | +//! @return session use EVENT mode. | |
936 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_connection_fail( | |
937 | + const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &rs_endpoint) | |
938 | +{ | |
939 | + EVENT_TAG status = FINALIZE; | |
940 | + thread_data_ptr session_data; | |
941 | + session_thread_data_map_it session_thread_it; | |
942 | + | |
943 | + try { | |
944 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
945 | + | |
946 | + session_thread_it = session_thread_data_map.find(thread_id); | |
947 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
948 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
949 | + formatter % boost::this_thread::get_id(); | |
950 | + putLogError(100049, formatter.str(), __FILE__, __LINE__); | |
951 | + throw - 1; | |
952 | + } | |
953 | + | |
954 | + session_data = session_thread_it->second; | |
955 | + | |
956 | + //set end flag ON | |
957 | + session_data->end_flag = END_FLAG_ON; | |
958 | + status = CLIENT_DISCONNECT; | |
959 | + } catch (...) { | |
960 | + status = FINALIZE; | |
961 | + } | |
962 | + | |
963 | + return status; | |
964 | +} | |
965 | +//! called from after realserver send. | |
966 | +//! @param[in] upstream thread id | |
967 | +//! @return session use EVENT mode. | |
968 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_send( | |
969 | + const boost::thread::id thread_id) | |
970 | +{ | |
971 | + EVENT_TAG status = FINALIZE; | |
972 | + thread_data_ptr session_data; | |
973 | + session_thread_data_map_it session_thread_it; | |
974 | + receive_data_map_it receive_data_it; | |
975 | + | |
976 | + try { | |
977 | + { | |
978 | + boost::mutex::scoped_lock sclock(session_thread_data_map_mutex); | |
979 | + | |
980 | + //thread_id check | |
981 | + session_thread_it = session_thread_data_map.find(thread_id); | |
982 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
983 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
984 | + formatter % boost::this_thread::get_id(); | |
985 | + putLogError(100052, formatter.str(), __FILE__, __LINE__); | |
986 | + throw - 1; | |
987 | + } | |
988 | + | |
989 | + session_data = session_thread_it->second; | |
990 | + } | |
991 | + | |
992 | + //endpoint check | |
993 | + receive_data_it = session_data->receive_data_map.find(session_data->client_endpoint_tcp); | |
994 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
995 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
996 | + formatter % boost::this_thread::get_id(); | |
997 | + putLogError(100053, formatter.str(), __FILE__, __LINE__); | |
998 | + throw - 1; | |
999 | + } | |
1000 | + | |
1001 | + receive_data &recv_data = receive_data_it->second; | |
1002 | + | |
1003 | + send_status_it it = recv_data.send_status_list.begin(); | |
1004 | + send_status_it it_end = recv_data.send_status_list.end(); | |
1005 | + | |
1006 | + //status list check | |
1007 | + it = std::adjacent_find(it, it_end, data_send_list_incorrect()); | |
1008 | + if (unlikely(it != it_end)) { | |
1009 | + boost::format formatter("Sending possible data is invalid. thread id : %d."); | |
1010 | + formatter % boost::this_thread::get_id(); | |
1011 | + putLogError(100054, formatter.str(), __FILE__, __LINE__); | |
1012 | + throw - 1; | |
1013 | + } | |
1014 | + | |
1015 | + //status list check | |
1016 | + it = recv_data.send_status_list.begin(); | |
1017 | + it = std::find_if(it, it_end, data_send_ok()); | |
1018 | + if (unlikely(it == it_end)) { | |
1019 | + boost::format formatter("Sending possible data is not existed. thread id : %d."); | |
1020 | + formatter % boost::this_thread::get_id(); | |
1021 | + putLogError(100055, formatter.str(), __FILE__, __LINE__); | |
1022 | + throw - 1; | |
1023 | + } | |
1024 | + | |
1025 | + //sending possible data is exist | |
1026 | + if (it->send_possible_size > 0) { | |
1027 | + //status remain SEND_OK | |
1028 | + it->status = SEND_OK; | |
1029 | + //offset recalc | |
1030 | + it->send_offset += it->send_end_size; | |
1031 | + | |
1032 | + //insert_position recalc | |
1033 | + for (std::list<edit_data>::iterator list_it = it->edit_data_list.begin(); list_it | |
1034 | + != it->edit_data_list.end(); ++list_it) { | |
1035 | + list_it->insert_posission -= it->send_end_size; | |
1036 | + } | |
1037 | + | |
1038 | + //send_end_size recalc | |
1039 | + it->send_end_size = 0; | |
1040 | + } | |
1041 | + //sending possible data is not exist | |
1042 | + else { | |
1043 | + //can receive from client continue | |
1044 | + if (it->send_rest_size > 0) { | |
1045 | + //change status from SEND_OK to SEND_CONTINUE | |
1046 | + it->status = SEND_CONTINUE; | |
1047 | + } | |
1048 | + //can not receive from client continue | |
1049 | + else { | |
1050 | + //change status from SEND_OK to SEND_END | |
1051 | + it->status = SEND_END; | |
1052 | + } | |
1053 | + } | |
1054 | + | |
1055 | + it = recv_data.send_status_list.begin(); | |
1056 | + it = find_if(it, it_end, data_send_ok()); | |
1057 | + //send_ok item is exist | |
1058 | + if (it != it_end) { | |
1059 | + status = REALSERVER_CONNECT; | |
1060 | + } | |
1061 | + //send_ok item is exist | |
1062 | + else { | |
1063 | + status = CLIENT_RECV; | |
1064 | + } | |
1065 | + } catch (...) { | |
1066 | + status = FINALIZE; | |
1067 | + } | |
1068 | + | |
1069 | + return status; | |
1070 | +} | |
1071 | + | |
1072 | +//! called from after sorryserver select | |
1073 | +//! @param[in] upstream thread id | |
1074 | +//! @param[in] sorryserver endpoint reference | |
1075 | +//! @return session use EVENT mode. | |
1076 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_sorryserver_select( | |
1077 | + const boost::thread::id thread_id, boost::asio::ip::tcp::endpoint &sorry_endpoint) | |
1078 | +{ | |
1079 | + EVENT_TAG status = FINALIZE; | |
1080 | + boost::asio::ip::tcp::endpoint client_endpoint; | |
1081 | + | |
1082 | + thread_data_ptr session_data; | |
1083 | + session_thread_data_map_it session_thread_it; | |
1084 | + receive_data_map_it receive_data_it; | |
1085 | + | |
1086 | + try { | |
1087 | + boost::mutex::scoped_lock sclock(session_thread_data_map_mutex); | |
1088 | + | |
1089 | + session_thread_it = session_thread_data_map.find(thread_id); | |
1090 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
1091 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
1092 | + formatter % boost::this_thread::get_id(); | |
1093 | + putLogError(100058, formatter.str(), __FILE__, __LINE__); | |
1094 | + throw - 1; | |
1095 | + } | |
1096 | + | |
1097 | + session_data = session_thread_it->second; | |
1098 | + //set sorry_endpoint | |
1099 | + session_data->target_endpoint = sorry_endpoint; | |
1100 | + | |
1101 | + //endpoint check | |
1102 | + receive_data_it = session_data->receive_data_map.find(session_data->client_endpoint_tcp); | |
1103 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
1104 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
1105 | + formatter % boost::this_thread::get_id(); | |
1106 | + putLogError(100059, formatter.str(), __FILE__, __LINE__); | |
1107 | + throw - 1; | |
1108 | + } | |
1109 | + | |
1110 | + status = SORRYSERVER_CONNECT; | |
1111 | + } catch (...) { | |
1112 | + status = FINALIZE; | |
1113 | + } | |
1114 | + | |
1115 | + return status; | |
1116 | +} | |
1117 | + | |
1118 | +//! called from after sorryserver connect | |
1119 | +//! @param[in] upstream thread id | |
1120 | +//! @param[out] send buffer reference. | |
1121 | +//! @param[out] send length | |
1122 | +//! @return session use EVENT mode. | |
1123 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_sorryserver_connect( | |
1124 | + const boost::thread::id thread_id, boost::array<char, MAX_BUFFER_SIZE>& sendbuffer, size_t &datalen) | |
1125 | +{ | |
1126 | + EVENT_TAG status = FINALIZE; | |
1127 | + size_t send_buffer_remian_size = 0; | |
1128 | + size_t copy_size = 0; | |
1129 | + const int send_buffer_end_size = sendbuffer.max_size(); | |
1130 | + thread_data_ptr session_data; | |
1131 | + session_thread_data_map_it session_thread_it; | |
1132 | + receive_data_map_it receive_data_it; | |
1133 | + | |
1134 | + try { | |
1135 | + { | |
1136 | + boost::mutex::scoped_lock sclock(session_thread_data_map_mutex); | |
1137 | + | |
1138 | + //thread id check | |
1139 | + session_thread_it = session_thread_data_map.find(thread_id); | |
1140 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
1141 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
1142 | + formatter % boost::this_thread::get_id(); | |
1143 | + putLogError(100063, formatter.str(), __FILE__, __LINE__); | |
1144 | + throw - 1; | |
1145 | + } | |
1146 | + | |
1147 | + session_data = session_thread_it->second; | |
1148 | + } | |
1149 | + | |
1150 | + //endpoint check | |
1151 | + receive_data_it = session_data->receive_data_map.find(session_data->client_endpoint_tcp); | |
1152 | + if (unlikely(receive_data_it | |
1153 | + == session_data->receive_data_map.end())) { | |
1154 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
1155 | + formatter % boost::this_thread::get_id(); | |
1156 | + putLogError(100064, formatter.str(), __FILE__, __LINE__); | |
1157 | + throw - 1; | |
1158 | + } | |
1159 | + | |
1160 | + //receive_buffer pointer check | |
1161 | + receive_data &recv_data = receive_data_it->second; | |
1162 | + if (unlikely(recv_data.receive_buffer == NULL)) { | |
1163 | + status = CLIENT_RECV; | |
1164 | + goto handle_sorryserver_connect_out; | |
1165 | + } | |
1166 | + | |
1167 | + //send list check | |
1168 | + send_status_it it = recv_data.send_status_list.begin(); | |
1169 | + send_status_it it_end = recv_data.send_status_list.end(); | |
1170 | + | |
1171 | + it = find_if(it, it_end, data_send_possible()); | |
1172 | + if (unlikely(it == it_end)) { | |
1173 | + boost::format formatter("Sending possible data is not existed. thread id : %d."); | |
1174 | + formatter % boost::this_thread::get_id(); | |
1175 | + putLogError(100066, formatter.str(), __FILE__, __LINE__); | |
1176 | + throw - 1; | |
1177 | + } | |
1178 | + | |
1179 | + //send buffer rest size initialization | |
1180 | + send_buffer_remian_size = send_buffer_end_size; | |
1181 | + | |
1182 | + //copy data as large as possible | |
1183 | + //send_possible_size is larger | |
1184 | + if (send_buffer_remian_size >= it->send_possible_size) { | |
1185 | + copy_size = it->send_possible_size; | |
1186 | + //copy data by send_possible size | |
1187 | + memcpy(sendbuffer.data(), recv_data.receive_buffer | |
1188 | + + it->send_offset, copy_size); | |
1189 | + it->send_end_size = it->send_possible_size; | |
1190 | + it->send_possible_size = 0; | |
1191 | + send_buffer_remian_size -= copy_size; | |
1192 | + } | |
1193 | + //buffer rest size is larger | |
1194 | + else { | |
1195 | + //copy data by buffer rest size | |
1196 | + memcpy(sendbuffer.data(), recv_data.receive_buffer | |
1197 | + + it->send_offset, send_buffer_remian_size); | |
1198 | + it->send_end_size = send_buffer_remian_size; | |
1199 | + it->send_possible_size -= send_buffer_remian_size; | |
1200 | + send_buffer_remian_size = 0; | |
1201 | + } | |
1202 | + | |
1203 | + //set copied data length | |
1204 | + datalen = send_buffer_end_size - send_buffer_remian_size; | |
1205 | + | |
1206 | + status = SORRYSERVER_SEND; | |
1207 | + } catch (...) { | |
1208 | + status = FINALIZE; | |
1209 | + } | |
1210 | + | |
1211 | +handle_sorryserver_connect_out: | |
1212 | + return status; | |
1213 | +} | |
1214 | + | |
1215 | +//! called from after sorryserver connection fail | |
1216 | +//! @param[in] upstream thread id | |
1217 | +//! @param[in] sorryserver endpoint reference. | |
1218 | +//! @return session use EVENT mode. | |
1219 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_sorryserver_connection_fail( | |
1220 | + const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &sorry_endpoint) | |
1221 | +{ | |
1222 | + EVENT_TAG status = FINALIZE; | |
1223 | + thread_data_ptr session_data; | |
1224 | + session_thread_data_map_it session_thread_it; | |
1225 | + | |
1226 | + try { | |
1227 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
1228 | + | |
1229 | + session_thread_it = session_thread_data_map.find(thread_id); | |
1230 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
1231 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
1232 | + formatter % boost::this_thread::get_id(); | |
1233 | + putLogError(100070, formatter.str(), __FILE__, __LINE__); | |
1234 | + throw - 1; | |
1235 | + } | |
1236 | + | |
1237 | + session_data = session_thread_it->second; | |
1238 | + | |
1239 | + //set end flag on | |
1240 | + session_data->end_flag = END_FLAG_ON; | |
1241 | + | |
1242 | + status = CLIENT_DISCONNECT; | |
1243 | + } catch (...) { | |
1244 | + status = FINALIZE; | |
1245 | + } | |
1246 | + | |
1247 | + return status; | |
1248 | +} | |
1249 | + | |
1250 | +//! called from after sorryserver send | |
1251 | +//! @param[in] upstream thread id | |
1252 | +//! @return session use EVENT mode. | |
1253 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_sorryserver_send( | |
1254 | + const boost::thread::id thread_id) | |
1255 | +{ | |
1256 | + EVENT_TAG status = FINALIZE; | |
1257 | + thread_data_ptr session_data; | |
1258 | + session_thread_data_map_it session_thread_it; | |
1259 | + receive_data_map_it receive_data_it; | |
1260 | + | |
1261 | + try { | |
1262 | + { | |
1263 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
1264 | + | |
1265 | + //thread_id check | |
1266 | + session_thread_it = session_thread_data_map.find(thread_id); | |
1267 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
1268 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
1269 | + formatter % boost::this_thread::get_id(); | |
1270 | + putLogError(100073, formatter.str(), __FILE__, __LINE__); | |
1271 | + throw - 1; | |
1272 | + } | |
1273 | + | |
1274 | + session_data = session_thread_it->second; | |
1275 | + } | |
1276 | + | |
1277 | + //endpoint check | |
1278 | + receive_data_it = session_data->receive_data_map.find(session_data->client_endpoint_tcp); | |
1279 | + if (unlikely(receive_data_it | |
1280 | + == session_data->receive_data_map.end())) { | |
1281 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
1282 | + formatter % boost::this_thread::get_id(); | |
1283 | + putLogError(100074, formatter.str(), __FILE__, __LINE__); | |
1284 | + throw - 1; | |
1285 | + } | |
1286 | + | |
1287 | + receive_data &recv_data = receive_data_it->second; | |
1288 | + | |
1289 | + send_status_it it = recv_data.send_status_list.begin(); | |
1290 | + send_status_it it_end = recv_data.send_status_list.end(); | |
1291 | + //status list check | |
1292 | + it = std::adjacent_find(it, it_end, data_send_list_incorrect()); | |
1293 | + if (unlikely(it != it_end)) { | |
1294 | + boost::format formatter("Sending possible data is invalid. thread id : %d."); | |
1295 | + formatter % boost::this_thread::get_id(); | |
1296 | + putLogError(100075, formatter.str(), __FILE__, __LINE__); | |
1297 | + throw - 1; | |
1298 | + } | |
1299 | + | |
1300 | + //status list check | |
1301 | + it = recv_data.send_status_list.begin(); | |
1302 | + it = find_if(it, it_end, data_send_ok()); | |
1303 | + if (unlikely(it == it_end)) { | |
1304 | + boost::format formatter("Sending possible data is not existed. thread id : %d."); | |
1305 | + formatter % boost::this_thread::get_id(); | |
1306 | + putLogError(100076, formatter.str(), __FILE__, __LINE__); | |
1307 | + throw - 1; | |
1308 | + } | |
1309 | + | |
1310 | + //sending possible data is exist | |
1311 | + if (it->send_possible_size > 0) { | |
1312 | + //status remain SEND_OK | |
1313 | + it->status = SEND_OK; | |
1314 | + //offset recalc | |
1315 | + it->send_offset += it->send_end_size; | |
1316 | + | |
1317 | + //insert_position recalc | |
1318 | + for (std::list<edit_data>::iterator list_it = it->edit_data_list.begin(); list_it | |
1319 | + != it->edit_data_list.end(); ++list_it) { | |
1320 | + list_it->insert_posission -= it->send_end_size; | |
1321 | + } | |
1322 | + | |
1323 | + //send_end_size recalc | |
1324 | + it->send_end_size = 0; | |
1325 | + } | |
1326 | + //sending possible data is not exist | |
1327 | + else { | |
1328 | + //can receive from client continue | |
1329 | + if (it->send_rest_size > 0) { | |
1330 | + //change status from SEND_OK to SEND_CONTINUE | |
1331 | + it->status = SEND_CONTINUE; | |
1332 | + } | |
1333 | + //can not receive from client continue | |
1334 | + else { | |
1335 | + //change status from SEND_OK to SEND_END | |
1336 | + it->status = SEND_END; | |
1337 | + } | |
1338 | + } | |
1339 | + | |
1340 | + it = recv_data.send_status_list.begin(); | |
1341 | + it = find_if(it, it_end, data_send_ok()); | |
1342 | + //send_ok item is exist | |
1343 | + if (it != it_end) { | |
1344 | + status = SORRYSERVER_CONNECT; | |
1345 | + } | |
1346 | + //send_ok item is exist | |
1347 | + else { | |
1348 | + status = CLIENT_RECV; | |
1349 | + } | |
1350 | + } catch (...) { | |
1351 | + status = FINALIZE; | |
1352 | + } | |
1353 | + | |
1354 | + return status; | |
1355 | +} | |
1356 | + | |
1357 | +//! called from after realserver receive.for UDP | |
1358 | +//! @param[in] downstream thread id | |
1359 | +//! @param[in] realserver UDP endpoint reference | |
1360 | +//! @param[in] receive from realserver buffer reference | |
1361 | +//! @param[in] recv data length | |
1362 | +//! @return session use EVENT mode. | |
1363 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_recv( | |
1364 | + const boost::thread::id thread_id, const boost::asio::ip::udp::endpoint &rs_endpoint, const boost::array < char, | |
1365 | + MAX_BUFFER_SIZE > & recvbuffer, const size_t recvlen) | |
1366 | +{ | |
1367 | + return STOP; | |
1368 | +} | |
1369 | + | |
1370 | +//! called from after realserver receive for TCP/IP | |
1371 | +//! @param[in] downstream thread id | |
1372 | +//! @param[in] realserver TCP/IP endpoint reference | |
1373 | +//! @param[in] realserver receive buffer reference. | |
1374 | +//! @param[in] recv data length | |
1375 | +//! @return session use EVENT mode. | |
1376 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_recv( | |
1377 | + const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &rs_endpoint, const boost::array < char, | |
1378 | + MAX_BUFFER_SIZE > & recvbuffer, const size_t recvlen) | |
1379 | +{ | |
1380 | + EVENT_TAG status = FINALIZE; | |
1381 | + size_t data_remain_start = 0; | |
1382 | + size_t data_remain_size = 0; | |
1383 | + size_t request_data_remain_size = 0; | |
1384 | + size_t buffer_size = 0; | |
1385 | + thread_data_ptr session_data; | |
1386 | + char *buffer1 = NULL; | |
1387 | + char *buffer2 = NULL; | |
1388 | + std::string str_value; | |
1389 | + session_thread_data_map_it session_thread_it; | |
1390 | + receive_data_map_it receive_data_it; | |
1391 | + | |
1392 | + //parameter check | |
1393 | + if (recvlen > recvbuffer.size()) { | |
1394 | + std::cerr << "protocol_module_simple::handle_realserver_recv() : Data size bigger than buffer size." << std::endl; | |
1395 | + boost::format formatter("Data size bigger than buffer size. thread id : %d."); | |
1396 | + formatter % boost::this_thread::get_id(); | |
1397 | + putLogError(100079, formatter.str(), __FILE__, __LINE__); | |
1398 | + return FINALIZE; | |
1399 | + } | |
1400 | + | |
1401 | + try { | |
1402 | + { | |
1403 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
1404 | + | |
1405 | + session_thread_it = session_thread_data_map.find(thread_id); | |
1406 | + if (unlikely(session_thread_it == session_thread_data_map.end() | |
1407 | + || session_thread_it->second == NULL)) { | |
1408 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
1409 | + formatter % boost::this_thread::get_id(); | |
1410 | + putLogError(100080, formatter.str(), __FILE__, __LINE__); | |
1411 | + throw - 1; | |
1412 | + } | |
1413 | + | |
1414 | + session_data = session_thread_it->second; | |
1415 | + } | |
1416 | + | |
1417 | + receive_data_it = session_data->receive_data_map.find(rs_endpoint); | |
1418 | + if (receive_data_it == session_data->receive_data_map.end()) { | |
1419 | + receive_data recv_data; | |
1420 | + session_data->receive_data_map[rs_endpoint] = recv_data; | |
1421 | + } | |
1422 | + | |
1423 | + session_data->target_endpoint = rs_endpoint; | |
1424 | + | |
1425 | + receive_data &recv_data = session_data->receive_data_map[rs_endpoint]; | |
1426 | + | |
1427 | + send_status_it it = recv_data.send_status_list.begin(); | |
1428 | + send_status_it it_end = recv_data.send_status_list.end(); | |
1429 | + | |
1430 | + //status list check | |
1431 | + it = std::find_if(it, it_end, data_send_ok()); | |
1432 | + if (unlikely(it != it_end)) { | |
1433 | + boost::format formatter("Sending data is not correct. thread id : %d."); | |
1434 | + formatter % boost::this_thread::get_id(); | |
1435 | + putLogError(100081, formatter.str(), __FILE__, __LINE__); | |
1436 | + throw - 1; | |
1437 | + } | |
1438 | + | |
1439 | + //status list check | |
1440 | + it = recv_data.send_status_list.begin(); | |
1441 | + it = std::adjacent_find(it, it_end, data_send_repeated()); | |
1442 | + if (unlikely(it != it_end)) { | |
1443 | + boost::format formatter("Sending data is not correct. thread id : %d."); | |
1444 | + formatter % boost::this_thread::get_id(); | |
1445 | + putLogError(100082, formatter.str(), __FILE__, __LINE__); | |
1446 | + throw - 1; | |
1447 | + } | |
1448 | + | |
1449 | + it = recv_data.send_status_list.begin(); | |
1450 | + //get original status info | |
1451 | + while (it != it_end) { | |
1452 | + //item status is SEND_END | |
1453 | + if (it->status == SEND_END) { | |
1454 | + //erase from list | |
1455 | + recv_data.send_status_list.erase(it++); | |
1456 | + continue; | |
1457 | + } | |
1458 | + //item status is SEND_CONTINUE | |
1459 | + else if (it->status == SEND_CONTINUE) { | |
1460 | + it->send_offset += it->send_end_size; | |
1461 | + data_remain_start = it->send_offset; | |
1462 | + break; | |
1463 | + } | |
1464 | + //item status is SEND_NG | |
1465 | + else { | |
1466 | + data_remain_start = it->send_offset; | |
1467 | + data_remain_size = it->unsend_size; | |
1468 | + break; | |
1469 | + } | |
1470 | + | |
1471 | + ++it; | |
1472 | + } | |
1473 | + //receive buffer process | |
1474 | + //buffer rest size < request size | |
1475 | + if (recv_data.receive_buffer_rest_size < recvlen) { | |
1476 | + //buffer max size < remain size + request size | |
1477 | + //buffer is need reallocate | |
1478 | + if (recv_data.receive_buffer_max_size < data_remain_size + recvlen) { | |
1479 | + //the buffer's size that will be allocated is exceed the upper limit value | |
1480 | + if (MAX_SIMPLE_MODULE_BUFFER_SIZE < data_remain_size + recvlen) { | |
1481 | + std::cerr << "protocol_module_simple::handle_realserver_recv() : the buffer's size that will be allocated is exceed the upper limit value." << std::endl; | |
1482 | + boost::format formatter("The buffer's size that will be allocated is exceed the upper limit value. thread id : %d."); | |
1483 | + formatter % boost::this_thread::get_id(); | |
1484 | + putLogError(100083, formatter.str(), __FILE__, __LINE__); | |
1485 | + | |
1486 | + return FINALIZE; | |
1487 | + } | |
1488 | + //receive_buffer1's memory allocate and initialization | |
1489 | + buffer_size = (data_remain_size + recvlen) > MAX_BUFFER_SIZE ? (data_remain_size + recvlen) : MAX_BUFFER_SIZE; | |
1490 | + buffer1 = new char[buffer_size]; | |
1491 | + memset(buffer1, 0, buffer_size); | |
1492 | + //receive_buffer2's memory allocate and initialization | |
1493 | + buffer2 = new char[buffer_size]; | |
1494 | + memset(buffer2, 0, buffer_size); | |
1495 | + | |
1496 | + //copy data from old buffer to new buffer | |
1497 | + memcpy(buffer1, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
1498 | + memcpy(buffer1 + data_remain_size, recvbuffer.data(), recvlen); | |
1499 | + //free old buffer1 and old buffer2 | |
1500 | + if (recv_data.receive_buffer1 != NULL) { | |
1501 | + delete[] recv_data.receive_buffer1; | |
1502 | + recv_data.receive_buffer1 = NULL; | |
1503 | + } | |
1504 | + | |
1505 | + if (recv_data.receive_buffer2 != NULL) { | |
1506 | + delete[] recv_data.receive_buffer2; | |
1507 | + recv_data.receive_buffer2 = NULL; | |
1508 | + } | |
1509 | + | |
1510 | + //set new buffer pointer | |
1511 | + recv_data.receive_buffer1 = buffer1; | |
1512 | + recv_data.receive_buffer2 = buffer2; | |
1513 | + recv_data.receive_buffer = recv_data.receive_buffer1; | |
1514 | + //set new buffer's max size | |
1515 | + recv_data.receive_buffer_max_size = buffer_size; | |
1516 | + } | |
1517 | + //buffer's max size >= remain data size + request size | |
1518 | + //buffer isn't need reallocate, but switch | |
1519 | + else { | |
1520 | + //pointer valid check | |
1521 | + if (unlikely(recv_data.receive_buffer1 == NULL || recv_data.receive_buffer2 == NULL)) { | |
1522 | + boost::format formatter("Invalid pointer. thread id : %d."); | |
1523 | + formatter % boost::this_thread::get_id(); | |
1524 | + putLogError(100084, formatter.str(), __FILE__, __LINE__); | |
1525 | + throw - 1; | |
1526 | + } | |
1527 | + //using buffer is buffer1 | |
1528 | + if (recv_data.receive_buffer == recv_data.receive_buffer1) { | |
1529 | + //buffer2 initialization | |
1530 | + memset(recv_data.receive_buffer2, 0, recv_data.receive_buffer_max_size); | |
1531 | + //copy data from buffer1 to buffer2 | |
1532 | + memcpy(recv_data.receive_buffer2, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
1533 | + memcpy(recv_data.receive_buffer2 + data_remain_size, recvbuffer.data(), recvlen); | |
1534 | + //set buffer2 as using buffer | |
1535 | + recv_data.receive_buffer = recv_data.receive_buffer2; | |
1536 | + } | |
1537 | + //using buffer is buffer2 | |
1538 | + else { | |
1539 | + //buffer1 initialization | |
1540 | + memset(recv_data.receive_buffer1, 0, recv_data.receive_buffer_max_size); | |
1541 | + //copy data from buffer2 to buffer1 | |
1542 | + memcpy(recv_data.receive_buffer1, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
1543 | + memcpy(recv_data.receive_buffer1 + data_remain_size, recvbuffer.data(), recvlen); | |
1544 | + //set buffer1 as using buffer | |
1545 | + recv_data.receive_buffer = recv_data.receive_buffer1; | |
1546 | + } | |
1547 | + } | |
1548 | + | |
1549 | + //set buffer's rest size | |
1550 | + recv_data.receive_buffer_rest_size = recv_data.receive_buffer_max_size - data_remain_size - recvlen; | |
1551 | + | |
1552 | + //remain_size recalc | |
1553 | + data_remain_size += recvlen; | |
1554 | + | |
1555 | + send_status_it it_begin = recv_data.send_status_list.begin(); | |
1556 | + send_status_it it_end = recv_data.send_status_list.end(); | |
1557 | + //offset recalc | |
1558 | + for (; it_begin != it_end; ++it_begin) { | |
1559 | + it_begin->send_offset -= data_remain_start; | |
1560 | + } | |
1561 | + } | |
1562 | + //buffer's rest size >= request size | |
1563 | + //copy directly | |
1564 | + else { | |
1565 | + //pointer valid check | |
1566 | + if (unlikely(recv_data.receive_buffer == NULL)) { | |
1567 | + boost::format formatter("Invalid pointer. thread id : %d."); | |
1568 | + formatter % boost::this_thread::get_id(); | |
1569 | + putLogError(100085, formatter.str(), __FILE__, __LINE__); | |
1570 | + throw - 1; | |
1571 | + } | |
1572 | + | |
1573 | + //copy data from parameter to using buffer | |
1574 | + memcpy(recv_data.receive_buffer + recv_data.receive_buffer_max_size - recv_data.receive_buffer_rest_size, | |
1575 | + recvbuffer.data(), recvlen); | |
1576 | + //buffer's rest size recalc | |
1577 | + recv_data.receive_buffer_rest_size -= recvlen; | |
1578 | + //remain data size recalc | |
1579 | + data_remain_size += recvlen; | |
1580 | + } | |
1581 | + | |
1582 | + it = recv_data.send_status_list.begin(); | |
1583 | + it_end = recv_data.send_status_list.end(); | |
1584 | + //request rest size initialization | |
1585 | + request_data_remain_size = recvlen; | |
1586 | + //original status process | |
1587 | + for (; it != it_end; ++it) { | |
1588 | + //status is SEND_CONTINUE | |
1589 | + if (it->status == SEND_CONTINUE) { | |
1590 | + //send rest size > request size | |
1591 | + if (it->send_rest_size > request_data_remain_size) { | |
1592 | + //send possible size recalc | |
1593 | + it->send_possible_size = request_data_remain_size; | |
1594 | + //send rest size recalc | |
1595 | + it->send_rest_size -= request_data_remain_size; | |
1596 | + //send end size recalc | |
1597 | + it->send_end_size = 0; | |
1598 | + //request size recalc | |
1599 | + request_data_remain_size = 0; | |
1600 | + } | |
1601 | + //send rest size <= request size | |
1602 | + else { | |
1603 | + //send possible size recalc | |
1604 | + it->send_possible_size = it->send_rest_size; | |
1605 | + //send rest size recalc | |
1606 | + request_data_remain_size -= it->send_rest_size; | |
1607 | + //send end size recalc | |
1608 | + it->send_end_size = 0; | |
1609 | + //request size recalc | |
1610 | + it->send_rest_size = 0; | |
1611 | + } | |
1612 | + //change status from SEND_CONTINUE to SEND_OK | |
1613 | + it->status = SEND_OK; | |
1614 | + } | |
1615 | + //status is SEND_NG | |
1616 | + else if (it->status == SEND_NG) { | |
1617 | + //send_rest_size recalc | |
1618 | + it->send_rest_size = it->unsend_size + request_data_remain_size; | |
1619 | + | |
1620 | + //recalc fields value according to send_rest_size and request rest size | |
1621 | + if (it->send_rest_size > it->unsend_size + request_data_remain_size) { | |
1622 | + it->send_possible_size = it->unsend_size + request_data_remain_size; | |
1623 | + it->send_rest_size -= (it->unsend_size + request_data_remain_size); | |
1624 | + it->send_end_size = 0; | |
1625 | + it->unsend_size = 0; | |
1626 | + request_data_remain_size = 0; | |
1627 | + } else { | |
1628 | + it->send_possible_size = it->send_rest_size; | |
1629 | + request_data_remain_size = it->unsend_size + request_data_remain_size - it->send_rest_size; | |
1630 | + it->send_end_size = 0; | |
1631 | + it->unsend_size = 0; | |
1632 | + it->send_rest_size = 0; | |
1633 | + } | |
1634 | + | |
1635 | + //change status from SEND_NG to SEND_OK | |
1636 | + it->status = SEND_OK; | |
1637 | + } | |
1638 | + //no request rest data to process | |
1639 | + if (request_data_remain_size <= 0) { | |
1640 | + break; | |
1641 | + } | |
1642 | + } | |
1643 | + | |
1644 | + //there are still rest data need to process | |
1645 | + //new status created and add to status list | |
1646 | + while (request_data_remain_size > 0) { | |
1647 | + //new status created | |
1648 | + send_status new_send_state; | |
1649 | + new_send_state.edit_division = EDIT_DIVISION_NO_EDIT; | |
1650 | + new_send_state.send_end_size = 0; | |
1651 | + new_send_state.send_offset = 0; | |
1652 | + new_send_state.send_possible_size = 0; | |
1653 | + new_send_state.unsend_size = 0; | |
1654 | + new_send_state.send_rest_size = 0; | |
1655 | + //status initialize to SEND_NG | |
1656 | + new_send_state.status = SEND_NG; | |
1657 | + //add new status to status_list | |
1658 | + recv_data.send_status_list.push_back(new_send_state); | |
1659 | + std::list<send_status>::reverse_iterator new_send_it = recv_data.send_status_list.rbegin(); | |
1660 | + //calc offset | |
1661 | + new_send_it->send_offset = recv_data.receive_buffer_max_size - recv_data.receive_buffer_rest_size | |
1662 | + - request_data_remain_size; | |
1663 | + | |
1664 | + new_send_it->send_rest_size = request_data_remain_size; | |
1665 | + | |
1666 | + //recalc fields value according to send_rest_size and request rest size | |
1667 | + if (new_send_it->send_rest_size > request_data_remain_size) { | |
1668 | + new_send_it->send_possible_size = request_data_remain_size; | |
1669 | + new_send_it->send_rest_size -= request_data_remain_size; | |
1670 | + new_send_it->send_end_size = 0; | |
1671 | + new_send_it->send_end_size = 0; | |
1672 | + request_data_remain_size = 0; | |
1673 | + } else { | |
1674 | + new_send_it->send_possible_size = new_send_it->send_rest_size; | |
1675 | + request_data_remain_size -= new_send_it->send_rest_size; | |
1676 | + new_send_it->send_end_size = 0; | |
1677 | + new_send_it->send_rest_size = 0; | |
1678 | + } | |
1679 | + | |
1680 | + //change status from SEND_NG to SEND_OK | |
1681 | + new_send_it->status = SEND_OK; | |
1682 | + } | |
1683 | + | |
1684 | + //search for send_possible item in status list | |
1685 | + send_status_it it_find = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), | |
1686 | + data_send_possible()); | |
1687 | + //the data that can be sent possible is exist | |
1688 | + if (it_find != recv_data.send_status_list.end()) { | |
1689 | + status = CLIENT_CONNECTION_CHECK; | |
1690 | + } | |
1691 | + //the data that can be sent possible is not exist | |
1692 | + else { | |
1693 | + status = REALSERVER_RECV; | |
1694 | + } | |
1695 | + } catch (...) { | |
1696 | + status = FINALIZE; | |
1697 | + } | |
1698 | + | |
1699 | + return status; | |
1700 | +} | |
1701 | + | |
1702 | + | |
1703 | + | |
1704 | +//! called from after sorryserver receive | |
1705 | +//! @param[in] downstream thread id | |
1706 | +//! @param[in] sorryserver endpoint reference | |
1707 | +//! @param[in] receive from realserver buffer reference. | |
1708 | +//! @param[in] recv data length | |
1709 | +//! @return session use EVENT mode | |
1710 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_sorryserver_recv( | |
1711 | + const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &sorry_endpoint, const boost::array < | |
1712 | + char, MAX_BUFFER_SIZE > & recvbuffer, const size_t recvlen) | |
1713 | +{ | |
1714 | + EVENT_TAG status = FINALIZE; | |
1715 | + size_t data_remain_start = 0; | |
1716 | + size_t data_remain_size = 0; | |
1717 | + size_t request_data_remain_size = 0; | |
1718 | + size_t buffer_size = 0; | |
1719 | + thread_data_ptr session_data; | |
1720 | + char *buffer1 = NULL; | |
1721 | + char *buffer2 = NULL; | |
1722 | + session_thread_data_map_it session_thread_it; | |
1723 | + receive_data_map_it receive_data_it; | |
1724 | + | |
1725 | + //parameter check | |
1726 | + if (recvlen > recvbuffer.size()) { | |
1727 | + std::cerr << "protocol_module_simple::handle_sorryserver_recv() : Data size bigger than buffer size." << std::endl; | |
1728 | + boost::format formatter("Data size bigger than buffer size. thread id : %d."); | |
1729 | + formatter % boost::this_thread::get_id(); | |
1730 | + putLogError(100090, formatter.str(), __FILE__, | |
1731 | + __LINE__); | |
1732 | + return FINALIZE; | |
1733 | + } | |
1734 | + | |
1735 | + try { | |
1736 | + { | |
1737 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
1738 | + | |
1739 | + session_thread_it = session_thread_data_map.find(thread_id); | |
1740 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
1741 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
1742 | + formatter % boost::this_thread::get_id(); | |
1743 | + putLogError(100091, formatter.str(), __FILE__, __LINE__); | |
1744 | + throw - 1; | |
1745 | + } | |
1746 | + | |
1747 | + session_data = session_thread_it->second; | |
1748 | + } | |
1749 | + | |
1750 | + receive_data_it = session_data->receive_data_map.find(sorry_endpoint); | |
1751 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
1752 | + receive_data recv_data; | |
1753 | + session_data->receive_data_map[sorry_endpoint] = recv_data; | |
1754 | + } | |
1755 | + | |
1756 | + session_data->target_endpoint = sorry_endpoint; | |
1757 | + | |
1758 | + receive_data &recv_data = session_data->receive_data_map[sorry_endpoint]; | |
1759 | + | |
1760 | + //status list check | |
1761 | + send_status_it it = recv_data.send_status_list.begin(); | |
1762 | + send_status_it it_end = recv_data.send_status_list.end(); | |
1763 | + it = std::find_if(it, it_end, data_send_ok()); | |
1764 | + if (unlikely(it != it_end)) { | |
1765 | + boost::format formatter("Sending data is invalid. thread id : %d."); | |
1766 | + formatter % boost::this_thread::get_id(); | |
1767 | + putLogError(100092, formatter.str(), __FILE__, __LINE__); | |
1768 | + throw - 1; | |
1769 | + } | |
1770 | + | |
1771 | + //status list check | |
1772 | + it = recv_data.send_status_list.begin(); | |
1773 | + it = std::adjacent_find(it, it_end, data_send_repeated()); | |
1774 | + if (unlikely(it != it_end)) { | |
1775 | + boost::format formatter("Sending data is invalid. thread id : %d."); | |
1776 | + formatter % boost::this_thread::get_id(); | |
1777 | + putLogError(100093, formatter.str(), __FILE__, __LINE__); | |
1778 | + throw - 1; | |
1779 | + } | |
1780 | + | |
1781 | + it = recv_data.send_status_list.begin(); | |
1782 | + //get original status info | |
1783 | + while (it != it_end) { | |
1784 | + //item status is SEND_END | |
1785 | + if (it->status == SEND_END) { | |
1786 | + //erase from list | |
1787 | + recv_data.send_status_list.erase(it++); | |
1788 | + continue; | |
1789 | + } | |
1790 | + //item status is SEND_CONTINUE | |
1791 | + else if (it->status == SEND_CONTINUE) { | |
1792 | + it->send_offset += it->send_end_size; | |
1793 | + data_remain_start = it->send_offset; | |
1794 | + break; | |
1795 | + } | |
1796 | + //item status is SEND_NG | |
1797 | + else { | |
1798 | + data_remain_start = it->send_offset; | |
1799 | + data_remain_size = it->unsend_size; | |
1800 | + break; | |
1801 | + } | |
1802 | + | |
1803 | + ++it; | |
1804 | + } | |
1805 | + //receive buffer process | |
1806 | + //buffer rest size < request size | |
1807 | + if (recv_data.receive_buffer_rest_size < recvlen) { | |
1808 | + //buffer max size < remain size + request size | |
1809 | + //buffer is need reallocate | |
1810 | + if (recv_data.receive_buffer_max_size < data_remain_size + recvlen) { | |
1811 | + //the buffer's size that will be allocated is exceed the upper limit value | |
1812 | + if (MAX_SIMPLE_MODULE_BUFFER_SIZE < data_remain_size + recvlen) { | |
1813 | + std::cerr << "protocol_module_simple::handle_sorryserver_recv() : the buffer's size that will be allocated is exceed the upper limit value." << std::endl; | |
1814 | + boost::format formatter("The buffer's size that will be allocated is exceed the upper limit value. thread id : %d."); | |
1815 | + formatter % boost::this_thread::get_id(); | |
1816 | + putLogError(100094, formatter.str(), __FILE__, __LINE__); | |
1817 | + return FINALIZE; | |
1818 | + } | |
1819 | + //receive_buffer1's memory allocate and initialization | |
1820 | + buffer_size = (data_remain_size + recvlen) > MAX_BUFFER_SIZE ? (data_remain_size + recvlen) : MAX_BUFFER_SIZE; | |
1821 | + buffer1 = new char[buffer_size]; | |
1822 | + memset(buffer1, 0, buffer_size); | |
1823 | + //receive_buffer2's memory allocate and initialization | |
1824 | + buffer2 = new char[buffer_size]; | |
1825 | + memset(buffer2, 0, buffer_size); | |
1826 | + | |
1827 | + //copy data from old buffer to new buffer | |
1828 | + memcpy(buffer1, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
1829 | + memcpy(buffer1 + data_remain_size, recvbuffer.data(), recvlen); | |
1830 | + //free old buffer1 and old buffer2 | |
1831 | + if (recv_data.receive_buffer1 != NULL) { | |
1832 | + delete[] recv_data.receive_buffer1; | |
1833 | + recv_data.receive_buffer1 = NULL; | |
1834 | + } | |
1835 | + | |
1836 | + if (recv_data.receive_buffer2 != NULL) { | |
1837 | + delete[] recv_data.receive_buffer2; | |
1838 | + recv_data.receive_buffer2 = NULL; | |
1839 | + } | |
1840 | + | |
1841 | + //set new buffer pointer | |
1842 | + recv_data.receive_buffer1 = buffer1; | |
1843 | + recv_data.receive_buffer2 = buffer2; | |
1844 | + recv_data.receive_buffer = recv_data.receive_buffer1; | |
1845 | + //set new buffer's max size | |
1846 | + recv_data.receive_buffer_max_size = buffer_size; | |
1847 | + } | |
1848 | + //buffer's max size >= remain data size + request size | |
1849 | + //buffer isn't need reallocate, but switch | |
1850 | + else { | |
1851 | + //pointer valid check | |
1852 | + if (unlikely(recv_data.receive_buffer1 == NULL || recv_data.receive_buffer2 == NULL)) { | |
1853 | + boost::format formatter("Invalid pointer. thread id : %d."); | |
1854 | + formatter % boost::this_thread::get_id(); | |
1855 | + putLogError(100095, formatter.str(), __FILE__, __LINE__); | |
1856 | + throw - 1; | |
1857 | + } | |
1858 | + //using buffer is buffer1 | |
1859 | + if (recv_data.receive_buffer == recv_data.receive_buffer1) { | |
1860 | + //buffer2 initialization | |
1861 | + memset(recv_data.receive_buffer2, 0, recv_data.receive_buffer_max_size); | |
1862 | + //copy data from buffer1 to buffer2 | |
1863 | + memcpy(recv_data.receive_buffer2, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
1864 | + memcpy(recv_data.receive_buffer2 + data_remain_size, recvbuffer.data(), recvlen); | |
1865 | + //set buffer2 as using buffer | |
1866 | + recv_data.receive_buffer = recv_data.receive_buffer2; | |
1867 | + } | |
1868 | + //using buffer is buffer2 | |
1869 | + else { | |
1870 | + //buffer1 initialization | |
1871 | + memset(recv_data.receive_buffer1, 0, recv_data.receive_buffer_max_size); | |
1872 | + //copy data from buffer2 to buffer1 | |
1873 | + memcpy(recv_data.receive_buffer1, recv_data.receive_buffer + data_remain_start, data_remain_size); | |
1874 | + memcpy(recv_data.receive_buffer1 + data_remain_size, recvbuffer.data(), recvlen); | |
1875 | + //set buffer1 as using buffer | |
1876 | + recv_data.receive_buffer = recv_data.receive_buffer1; | |
1877 | + } | |
1878 | + } | |
1879 | + | |
1880 | + //set buffer's rest size | |
1881 | + recv_data.receive_buffer_rest_size = recv_data.receive_buffer_max_size - data_remain_size - recvlen; | |
1882 | + | |
1883 | + //remain_size recalc | |
1884 | + data_remain_size += recvlen; | |
1885 | + | |
1886 | + send_status_it it_begin = recv_data.send_status_list.begin(); | |
1887 | + send_status_it it_end = recv_data.send_status_list.end(); | |
1888 | + //offset recalc | |
1889 | + for (; it_begin != it_end; ++it_begin) { | |
1890 | + it_begin->send_offset -= data_remain_start; | |
1891 | + } | |
1892 | + } | |
1893 | + //buffer's rest size >= request size | |
1894 | + //copy directly | |
1895 | + else { | |
1896 | + //pointer valid check | |
1897 | + if (unlikely(recv_data.receive_buffer == NULL)) { | |
1898 | + boost::format formatter("Invalid pointer. thread id : %d"); | |
1899 | + formatter % boost::this_thread::get_id(); | |
1900 | + putLogError(100096, formatter.str(), __FILE__, __LINE__); | |
1901 | + throw - 1; | |
1902 | + } | |
1903 | + | |
1904 | + //copy data from parameter to using buffer | |
1905 | + memcpy(recv_data.receive_buffer + recv_data.receive_buffer_max_size - recv_data.receive_buffer_rest_size, | |
1906 | + recvbuffer.data(), recvlen); | |
1907 | + //buffer's rest size recalc | |
1908 | + recv_data.receive_buffer_rest_size -= recvlen; | |
1909 | + //remain data size recalc | |
1910 | + data_remain_size += recvlen; | |
1911 | + } | |
1912 | + | |
1913 | + it = recv_data.send_status_list.begin(); | |
1914 | + it_end = recv_data.send_status_list.end(); | |
1915 | + //request rest size initialization | |
1916 | + request_data_remain_size = recvlen; | |
1917 | + //original status process | |
1918 | + for (; it != it_end; ++it) { | |
1919 | + //status is SEND_CONTINUE | |
1920 | + if (it->status == SEND_CONTINUE) { | |
1921 | + // | |
1922 | + if (it->send_rest_size > request_data_remain_size) { | |
1923 | + it->send_possible_size = request_data_remain_size; | |
1924 | + it->send_rest_size -= request_data_remain_size; | |
1925 | + it->send_end_size = 0; | |
1926 | + request_data_remain_size = 0; | |
1927 | + } else { | |
1928 | + it->send_possible_size = it->send_rest_size; | |
1929 | + request_data_remain_size -= it->send_rest_size; | |
1930 | + it->send_end_size = 0; | |
1931 | + it->send_rest_size = 0; | |
1932 | + } | |
1933 | + | |
1934 | + //change status from SEND_CONTINUE to SEND_OK | |
1935 | + it->status = SEND_OK; | |
1936 | + } | |
1937 | + //status is SEND_NG | |
1938 | + else if (it->status == SEND_NG) { | |
1939 | + it->send_rest_size = it->unsend_size + request_data_remain_size; | |
1940 | + | |
1941 | + //recalc fields value according to send_rest_size and request rest size | |
1942 | + if (it->send_rest_size > it->unsend_size + request_data_remain_size) { | |
1943 | + it->send_possible_size = it->unsend_size + request_data_remain_size; | |
1944 | + it->send_rest_size -= (it->unsend_size + request_data_remain_size); | |
1945 | + it->send_end_size = 0; | |
1946 | + it->unsend_size = 0; | |
1947 | + request_data_remain_size = 0; | |
1948 | + } else { | |
1949 | + it->send_possible_size = it->send_rest_size; | |
1950 | + request_data_remain_size = it->unsend_size + request_data_remain_size - it->send_rest_size; | |
1951 | + it->send_end_size = 0; | |
1952 | + it->unsend_size = 0; | |
1953 | + it->send_rest_size = 0; | |
1954 | + } | |
1955 | + | |
1956 | + //change status from SEND_NG to SEND_OK | |
1957 | + it->status = SEND_OK; | |
1958 | + } | |
1959 | + //no request rest data to process | |
1960 | + if (request_data_remain_size <= 0) { | |
1961 | + break; | |
1962 | + } | |
1963 | + } | |
1964 | + | |
1965 | + //there are still rest data need to process | |
1966 | + //new status created and add to status list | |
1967 | + while (request_data_remain_size > 0) { | |
1968 | + //new status created | |
1969 | + send_status new_send_state; | |
1970 | + new_send_state.edit_division = EDIT_DIVISION_NO_EDIT; | |
1971 | + new_send_state.send_end_size = 0; | |
1972 | + new_send_state.send_offset = 0; | |
1973 | + new_send_state.send_possible_size = 0; | |
1974 | + new_send_state.unsend_size = 0; | |
1975 | + new_send_state.send_rest_size = 0; | |
1976 | + //status initialize to SEND_NG | |
1977 | + new_send_state.status = SEND_NG; | |
1978 | + //add new status to status_list | |
1979 | + recv_data.send_status_list.push_back(new_send_state); | |
1980 | + std::list<send_status>::reverse_iterator new_send_it = recv_data.send_status_list.rbegin(); | |
1981 | + //calc offset | |
1982 | + new_send_it->send_offset = recv_data.receive_buffer_max_size - recv_data.receive_buffer_rest_size | |
1983 | + - request_data_remain_size; | |
1984 | + | |
1985 | + new_send_it->send_rest_size = request_data_remain_size; | |
1986 | + | |
1987 | + //recalc fields value according to send_rest_size and request rest size | |
1988 | + if (new_send_it->send_rest_size > request_data_remain_size) { | |
1989 | + new_send_it->send_possible_size = request_data_remain_size; | |
1990 | + new_send_it->send_rest_size -= request_data_remain_size; | |
1991 | + new_send_it->send_end_size = 0; | |
1992 | + request_data_remain_size = 0; | |
1993 | + } else { | |
1994 | + new_send_it->send_possible_size = new_send_it->send_rest_size; | |
1995 | + request_data_remain_size -= new_send_it->send_rest_size; | |
1996 | + new_send_it->send_end_size = 0; | |
1997 | + new_send_it->send_rest_size = 0; | |
1998 | + } | |
1999 | + | |
2000 | + //change status from SEND_NG to SEND_OK | |
2001 | + new_send_it->status = SEND_OK; | |
2002 | + } | |
2003 | + | |
2004 | + //search for send_possible item in status list | |
2005 | + send_status_it it_find = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), | |
2006 | + data_send_possible()); | |
2007 | + //the data that can be sent possible is exist | |
2008 | + if (it_find != recv_data.send_status_list.end()) { | |
2009 | + status = CLIENT_CONNECTION_CHECK; | |
2010 | + } | |
2011 | + //the data that can be sent possible is not exist | |
2012 | + else { | |
2013 | + status = SORRYSERVER_RECV; | |
2014 | + } | |
2015 | + } catch (...) { | |
2016 | + status = FINALIZE; | |
2017 | + } | |
2018 | + | |
2019 | + return status; | |
2020 | +} | |
2021 | + | |
2022 | +//! called from UPSTREAM thread. make module original message. | |
2023 | +//! @param[in] downstream thread id. | |
2024 | +//! @return session use EVENT mode | |
2025 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_response_send_inform( | |
2026 | + const boost::thread::id thread_id) | |
2027 | +{ | |
2028 | + return STOP; | |
2029 | +} | |
2030 | + | |
2031 | +//! called from after client connection check. use TCP/IP only. create client send message. | |
2032 | +//! @param[in] downstream thread id | |
2033 | +//! @param[out] send buffer reference | |
2034 | +//! @param[out] send data length | |
2035 | +//! @return session use EVENT mode | |
2036 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_client_connection_check( | |
2037 | + const boost::thread::id thread_id, boost::array<char, MAX_BUFFER_SIZE>& sendbuffer, size_t &datalen) | |
2038 | +{ | |
2039 | + EVENT_TAG status = FINALIZE; | |
2040 | + size_t send_buffer_size = sendbuffer.max_size(); | |
2041 | + thread_data_ptr session_data; | |
2042 | + session_thread_data_map_it session_thread_it; | |
2043 | + receive_data_map_it receive_data_it; | |
2044 | + | |
2045 | + try { | |
2046 | + { | |
2047 | + boost::mutex::scoped_lock sclock(session_thread_data_map_mutex); | |
2048 | + | |
2049 | + session_thread_it = session_thread_data_map.find(thread_id); | |
2050 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
2051 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
2052 | + formatter % boost::this_thread::get_id(); | |
2053 | + putLogError(100101, formatter.str(), __FILE__, __LINE__); | |
2054 | + throw - 1; | |
2055 | + } | |
2056 | + | |
2057 | + session_data = session_thread_it->second; | |
2058 | + } | |
2059 | + | |
2060 | + receive_data_it = session_data->receive_data_map.find(session_data->target_endpoint); | |
2061 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
2062 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
2063 | + formatter % boost::this_thread::get_id(); | |
2064 | + putLogError(100102, formatter.str(), __FILE__, __LINE__); | |
2065 | + throw - 1; | |
2066 | + } | |
2067 | + | |
2068 | + receive_data &recv_data = receive_data_it->second; | |
2069 | + | |
2070 | + //get the data that can be sent possible | |
2071 | + send_status_it it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), | |
2072 | + data_send_possible()); | |
2073 | + if (unlikely(it == recv_data.send_status_list.end())) { | |
2074 | + boost::format formatter("Sending possible data is not existed. thread id : %d."); | |
2075 | + formatter % boost::this_thread::get_id(); | |
2076 | + putLogError(100103, formatter.str(), __FILE__, __LINE__); | |
2077 | + throw - 1; | |
2078 | + } | |
2079 | + | |
2080 | + //buffer size >= sending_possible size | |
2081 | + if (send_buffer_size > it->send_possible_size) { | |
2082 | + //copy data from receive_buffer to sendbuffer by sending_possible size | |
2083 | + memcpy(sendbuffer.data(), recv_data.receive_buffer + it->send_offset, it->send_possible_size); | |
2084 | + //send_end_size recalc | |
2085 | + it->send_end_size = it->send_possible_size; | |
2086 | + //set copied data length | |
2087 | + datalen = it->send_possible_size; | |
2088 | + //sending_possible size recalc | |
2089 | + it->send_possible_size = 0; | |
2090 | + } | |
2091 | + //buffer size < sending_possible size | |
2092 | + else { | |
2093 | + //copy data from receive_buffer to sendbuffer by buffer size | |
2094 | + memcpy(sendbuffer.data(), recv_data.receive_buffer + it->send_offset, send_buffer_size); | |
2095 | + //send_end_size recalc | |
2096 | + it->send_end_size = send_buffer_size; | |
2097 | + //sending_possible size recalc | |
2098 | + it->send_possible_size -= send_buffer_size; | |
2099 | + //set copied data length | |
2100 | + datalen = send_buffer_size; | |
2101 | + } | |
2102 | + | |
2103 | + status = CLIENT_SEND; | |
2104 | + } catch (...) { | |
2105 | + status = FINALIZE; | |
2106 | + } | |
2107 | + | |
2108 | + return status; | |
2109 | +} | |
2110 | + | |
2111 | +//! called from after client select. use UDP only | |
2112 | +//! @param[in] downstream thread id | |
2113 | +//! @param[in] client udp endpoint | |
2114 | +//! @param[out] send buffer reference | |
2115 | +//! @param[out] send data length | |
2116 | +//! @return session use EVENT mode | |
2117 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_client_select( | |
2118 | + const boost::thread::id thread_id, boost::asio::ip::udp::endpoint &cl_endpoint, boost::array < char, | |
2119 | + MAX_BUFFER_SIZE > & sendbuffer, size_t &datalen) | |
2120 | +{ | |
2121 | + return STOP; | |
2122 | +} | |
2123 | + | |
2124 | +//! called from after client send | |
2125 | +//! @param[in] downstream thread id | |
2126 | +//! @return session use EVENT mode | |
2127 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_client_send( | |
2128 | + const boost::thread::id thread_id) | |
2129 | +{ | |
2130 | + EVENT_TAG status = FINALIZE; | |
2131 | + thread_data_ptr session_data; | |
2132 | + session_thread_data_map_it session_thread_it; | |
2133 | + receive_data_map_it receive_data_it; | |
2134 | + | |
2135 | + try { | |
2136 | + { | |
2137 | + boost::mutex::scoped_lock sclock(session_thread_data_map_mutex); | |
2138 | + //thread_id check | |
2139 | + session_thread_it = session_thread_data_map.find(thread_id); | |
2140 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
2141 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
2142 | + formatter % boost::this_thread::get_id(); | |
2143 | + putLogError(100106, formatter.str(), __FILE__, __LINE__); | |
2144 | + throw - 1; | |
2145 | + } | |
2146 | + session_data = session_thread_it->second; | |
2147 | + } | |
2148 | + //endpoint check | |
2149 | + receive_data_it = session_data->receive_data_map.find(session_data->target_endpoint); | |
2150 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
2151 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
2152 | + formatter % boost::this_thread::get_id(); | |
2153 | + putLogError(100107, formatter.str(), __FILE__, __LINE__); | |
2154 | + throw - 1; | |
2155 | + } | |
2156 | + | |
2157 | + receive_data &recv_data = receive_data_it->second; | |
2158 | + | |
2159 | + send_status_it it = recv_data.send_status_list.begin(); | |
2160 | + send_status_it it_end = recv_data.send_status_list.end(); | |
2161 | + | |
2162 | + //check status list | |
2163 | + it = std::adjacent_find(it, it_end, data_send_list_incorrect()); | |
2164 | + if (unlikely(it != it_end)) { | |
2165 | + boost::format formatter("Sending possible data is invalid. thread id : %d."); | |
2166 | + formatter % boost::this_thread::get_id(); | |
2167 | + putLogError(100108, formatter.str(), __FILE__, __LINE__); | |
2168 | + throw - 1; | |
2169 | + } | |
2170 | + //status list check | |
2171 | + it = recv_data.send_status_list.begin(); | |
2172 | + it = find_if(it, it_end, data_send_ok()); | |
2173 | + if (unlikely(it == it_end)) { | |
2174 | + boost::format formatter("Sending possible data is not existed. thread id : %d."); | |
2175 | + formatter % boost::this_thread::get_id(); | |
2176 | + putLogError(100109, formatter.str(), __FILE__, __LINE__); | |
2177 | + throw - 1; | |
2178 | + } | |
2179 | + | |
2180 | + //sending possible data is exist | |
2181 | + if (it->send_possible_size > 0) { | |
2182 | + //status remain SEND_OK | |
2183 | + it->status = SEND_OK; | |
2184 | + //offset recalc | |
2185 | + it->send_offset += it->send_end_size; | |
2186 | + //send_end_size recalc | |
2187 | + it->send_end_size = 0; | |
2188 | + } | |
2189 | + //sending possible data is not exist | |
2190 | + else { | |
2191 | + //can receive from client continue | |
2192 | + if (it->send_rest_size > 0) { | |
2193 | + //change status from SEND_OK to SEND_CONTINUE | |
2194 | + it->status = SEND_CONTINUE; | |
2195 | + } | |
2196 | + //can not receive from client continue | |
2197 | + else { | |
2198 | + //change status from SEND_OK to SEND_END | |
2199 | + it->status = SEND_END; | |
2200 | + } | |
2201 | + } | |
2202 | + | |
2203 | + it = recv_data.send_status_list.begin(); | |
2204 | + it = find_if(it, it_end, data_send_ok()); | |
2205 | + //send_ok item is exist | |
2206 | + if (it != it_end) { | |
2207 | + status = CLIENT_CONNECTION_CHECK; | |
2208 | + } | |
2209 | + //send_ok item is not exist | |
2210 | + else { | |
2211 | + //end flag is on | |
2212 | + if (session_data->end_flag == END_FLAG_ON) { | |
2213 | + status = CLIENT_DISCONNECT; | |
2214 | + } | |
2215 | + //end flag is off | |
2216 | + else { | |
2217 | + //sorry flag is on | |
2218 | + if (session_data->sorry_flag == SORRY_FLAG_ON) { | |
2219 | + status = SORRYSERVER_RECV; | |
2220 | + } | |
2221 | + //sorry flag is off | |
2222 | + else { | |
2223 | + status = REALSERVER_RECV; | |
2224 | + } | |
2225 | + } | |
2226 | + } | |
2227 | + } catch (...) { | |
2228 | + status = FINALIZE; | |
2229 | + } | |
2230 | + | |
2231 | + return status; | |
2232 | +} | |
2233 | + | |
2234 | +//! call from client disconnect event. use upstream thread and downstream thread. | |
2235 | +//! @param[in] upstream and downstream thread id( check! one thread one event! ) | |
2236 | +//! @return session use EVENT mode | |
2237 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_client_disconnect( | |
2238 | + const boost::thread::id thread_id) | |
2239 | +{ | |
2240 | + return FINALIZE; | |
2241 | +} | |
2242 | + | |
2243 | +//! call from sorry mode event. use upstream thread and downstream thread | |
2244 | +//! @param[in] upstream and downstream thread id( check! one thread one event and first time call pattern ) | |
2245 | +//! @return session use EVENT mode | |
2246 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_sorry_enable( | |
2247 | + const boost::thread::id thread_id) | |
2248 | +{ | |
2249 | + EVENT_TAG status = FINALIZE; | |
2250 | + boost::asio::ip::tcp::endpoint endpoint; | |
2251 | + bool send_possible = false; | |
2252 | + bool send_continue = false; | |
2253 | + bool send_disable = false; | |
2254 | + thread_data_ptr session_data; | |
2255 | + session_thread_data_map_it session_thread_it; | |
2256 | + receive_data_map_it receive_data_it; | |
2257 | + | |
2258 | + try { | |
2259 | + { | |
2260 | + boost::mutex::scoped_lock slock(session_thread_data_map_mutex); | |
2261 | + //check thread_id | |
2262 | + session_thread_it = session_thread_data_map.find(thread_id); | |
2263 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
2264 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
2265 | + formatter % boost::this_thread::get_id(); | |
2266 | + putLogError(100112, formatter.str(), __FILE__, __LINE__); | |
2267 | + throw - 1; | |
2268 | + } | |
2269 | + | |
2270 | + session_data = session_thread_it->second; | |
2271 | + } | |
2272 | + //check endpoint | |
2273 | + endpoint = session_data->thread_division == THREAD_DIVISION_UP_STREAM ? session_data->client_endpoint_tcp | |
2274 | + : session_data->target_endpoint; | |
2275 | + receive_data_it = session_data->receive_data_map.find(endpoint); | |
2276 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
2277 | + //must be down thread | |
2278 | + if (unlikely(session_data->thread_division == THREAD_DIVISION_UP_STREAM)) { | |
2279 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
2280 | + formatter % boost::this_thread::get_id(); | |
2281 | + putLogError(100113, formatter.str(), __FILE__, __LINE__); | |
2282 | + throw - 1; | |
2283 | + } | |
2284 | + session_data->sorry_flag = SORRY_FLAG_ON; | |
2285 | + status = SORRYSERVER_RECV; | |
2286 | + } else { | |
2287 | + receive_data &recv_data = receive_data_it->second; | |
2288 | + | |
2289 | + //get this thread sending possible data | |
2290 | + send_status_it it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), | |
2291 | + data_send_possible()); | |
2292 | + if (it != recv_data.send_status_list.end()) { | |
2293 | + send_possible = true; | |
2294 | + } | |
2295 | + | |
2296 | + it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), data_send_continue()); | |
2297 | + if (it != recv_data.send_status_list.end()) { | |
2298 | + send_continue = true; | |
2299 | + } | |
2300 | + | |
2301 | + it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), data_send_disable()); | |
2302 | + if (it != recv_data.send_status_list.end()) { | |
2303 | + send_disable = true; | |
2304 | + } | |
2305 | + | |
2306 | + //up thread | |
2307 | + if (session_data->thread_division == THREAD_DIVISION_UP_STREAM) { | |
2308 | + //accept_end_flag is off | |
2309 | + if (session_data->accept_end_flag == ACCEPT_END_FLAG_OFF) { | |
2310 | + //set sorry flag on | |
2311 | + session_data->sorry_flag = SORRY_FLAG_ON; | |
2312 | + status = ACCEPT; | |
2313 | + } | |
2314 | + //accept_end_flag is on | |
2315 | + else { | |
2316 | + //set sorry flag on | |
2317 | + if (session_data->sorry_flag == SORRY_FLAG_ON) { | |
2318 | + if (send_possible) { | |
2319 | + status = SORRYSERVER_CONNECT; | |
2320 | + } else { | |
2321 | + status = SORRYSERVER_SELECT; | |
2322 | + } | |
2323 | + | |
2324 | + } | |
2325 | + //set sorry flag off | |
2326 | + else { | |
2327 | + //the data that can be sent continue is exist | |
2328 | + if (send_continue) { | |
2329 | + //set end flag on | |
2330 | + session_data->end_flag = END_FLAG_ON; | |
2331 | + status = REALSERVER_DISCONNECT; | |
2332 | + } | |
2333 | + //the data that can be sent continue is not exist | |
2334 | + else { | |
2335 | + //set sorryserver_switch_flag on | |
2336 | + session_data->sorryserver_switch_flag = SORRYSERVER_SWITCH_FLAG_ON; | |
2337 | + //set sorry_flag on | |
2338 | + session_data->sorry_flag = SORRY_FLAG_ON; | |
2339 | + status = REALSERVER_DISCONNECT; | |
2340 | + } | |
2341 | + } | |
2342 | + } | |
2343 | + } | |
2344 | + //down thread | |
2345 | + else { | |
2346 | + //sorry_flag is on | |
2347 | + if (session_data->sorry_flag == SORRY_FLAG_ON) { | |
2348 | + //sending possible data is exist | |
2349 | + if (send_possible) { | |
2350 | + status = CLIENT_CONNECTION_CHECK; | |
2351 | + } | |
2352 | + //sending possible data is not exist | |
2353 | + else { | |
2354 | + status = SORRYSERVER_RECV; | |
2355 | + } | |
2356 | + } | |
2357 | + //sorry_flag is off | |
2358 | + else { | |
2359 | + //set sorry_flag on | |
2360 | + session_data->sorry_flag = SORRY_FLAG_ON; | |
2361 | + session_data->sorryserver_switch_flag = SORRYSERVER_SWITCH_FLAG_ON; | |
2362 | + | |
2363 | + //sending NG data is exist or send_rest_size > 0 | |
2364 | + if (send_disable) { | |
2365 | + //set end flag on | |
2366 | + session_data->end_flag = END_FLAG_ON; | |
2367 | + status = REALSERVER_DISCONNECT; | |
2368 | + } | |
2369 | + else { | |
2370 | + //sending possible data is exist | |
2371 | + if (send_possible) { | |
2372 | + status = CLIENT_CONNECTION_CHECK; | |
2373 | + } | |
2374 | + //sending possible data is not exist | |
2375 | + else { | |
2376 | + status = SORRYSERVER_RECV; | |
2377 | + } | |
2378 | + } | |
2379 | + } | |
2380 | + } | |
2381 | + } | |
2382 | + } catch (...) { | |
2383 | + status = FINALIZE; | |
2384 | + } | |
2385 | + | |
2386 | + return status; | |
2387 | +} | |
2388 | + | |
2389 | +//! call from sorry mode disable. use upstream thread and downstream thread. | |
2390 | +//! @param[in] upstream and downstream thread id( check! one thread one event ) | |
2391 | +//! @return session use EVENT mode | |
2392 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_sorry_disable( | |
2393 | + const boost::thread::id thread_id) | |
2394 | +{ | |
2395 | + EVENT_TAG status = FINALIZE; | |
2396 | + boost::asio::ip::tcp::endpoint endpoint; | |
2397 | + bool send_possible = false; | |
2398 | + bool send_disable = false; | |
2399 | + bool send_continue = false; | |
2400 | + thread_data_ptr session_data; | |
2401 | + | |
2402 | + try { | |
2403 | + { | |
2404 | + boost::mutex::scoped_lock sclock(session_thread_data_map_mutex); | |
2405 | + //check thread_id | |
2406 | + session_thread_data_map_it session_thread_it = session_thread_data_map.find(thread_id); | |
2407 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
2408 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
2409 | + formatter % boost::this_thread::get_id(); | |
2410 | + putLogError(100116, formatter.str(), __FILE__, __LINE__); | |
2411 | + throw - 1; | |
2412 | + } | |
2413 | + //check pointer | |
2414 | + session_data = session_thread_it->second; | |
2415 | + } | |
2416 | + //check endpoint | |
2417 | + endpoint = session_data->thread_division == THREAD_DIVISION_UP_STREAM ? session_data->client_endpoint_tcp | |
2418 | + : session_data->target_endpoint; | |
2419 | + receive_data_map_it receive_data_it = session_data->receive_data_map.find(endpoint); | |
2420 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
2421 | + //must be down thread | |
2422 | + if (unlikely(session_data->thread_division == THREAD_DIVISION_UP_STREAM)) { | |
2423 | + boost::format formatter("Invalid endpoint. thread id : %d."); | |
2424 | + formatter % boost::this_thread::get_id(); | |
2425 | + putLogError(100117, formatter.str(), __FILE__, __LINE__); | |
2426 | + throw - 1; | |
2427 | + } | |
2428 | + | |
2429 | + session_data->sorry_flag = SORRY_FLAG_OFF; | |
2430 | + status = REALSERVER_RECV; | |
2431 | + } else { | |
2432 | + receive_data &recv_data = receive_data_it->second; | |
2433 | + | |
2434 | + //get this thread sending possible data | |
2435 | + send_status_it it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), | |
2436 | + data_send_possible()); | |
2437 | + if (it != recv_data.send_status_list.end()) { | |
2438 | + send_possible = true; | |
2439 | + } | |
2440 | + | |
2441 | + //sending NG data is exist or send_rest_size > 0 | |
2442 | + it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), data_send_disable()); | |
2443 | + if (it != recv_data.send_status_list.end()) { | |
2444 | + send_disable = true; | |
2445 | + } | |
2446 | + | |
2447 | + //the data that can be sent continue is exist | |
2448 | + it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), data_send_continue()); | |
2449 | + if (it != recv_data.send_status_list.end()) { | |
2450 | + send_continue = true; | |
2451 | + } | |
2452 | + | |
2453 | + //up thread | |
2454 | + if (session_data->thread_division == THREAD_DIVISION_UP_STREAM) { | |
2455 | + //accept_end_flag is off | |
2456 | + if (session_data->accept_end_flag == ACCEPT_END_FLAG_OFF) { | |
2457 | + //set sorry flag off | |
2458 | + session_data->sorry_flag = SORRY_FLAG_OFF; | |
2459 | + status = ACCEPT; | |
2460 | + } | |
2461 | + //accept_end_flag is on | |
2462 | + else { | |
2463 | + //sorry flag is on | |
2464 | + if (session_data->sorry_flag == SORRY_FLAG_ON) { | |
2465 | + //the data that can be sent continue is exist | |
2466 | + if (send_continue) { | |
2467 | + //set end flag on | |
2468 | + session_data->end_flag = END_FLAG_ON; | |
2469 | + status = SORRYSERVER_DISCONNECT; | |
2470 | + } | |
2471 | + //the data that can be sent continue is not exist | |
2472 | + else { | |
2473 | + //set realserver_switch_flag on | |
2474 | + session_data->realserver_switch_flag = REALSERVER_SWITCH_FLAG_ON; | |
2475 | + //set sorry_flag off | |
2476 | + session_data->sorry_flag = SORRY_FLAG_OFF; | |
2477 | + status = SORRYSERVER_DISCONNECT; | |
2478 | + } | |
2479 | + } | |
2480 | + //sorry flag is off | |
2481 | + else { | |
2482 | + if (send_possible) { | |
2483 | + status = REALSERVER_CONNECT; | |
2484 | + } else { | |
2485 | + status = REALSERVER_SELECT; | |
2486 | + } | |
2487 | + } | |
2488 | + } | |
2489 | + } | |
2490 | + //down thread | |
2491 | + else { | |
2492 | + //sorry_flag is on | |
2493 | + if (session_data->sorry_flag == SORRY_FLAG_ON) { | |
2494 | + //set sorry_flag off | |
2495 | + session_data->sorry_flag = SORRY_FLAG_OFF; | |
2496 | + session_data->realserver_switch_flag = REALSERVER_SWITCH_FLAG_ON; | |
2497 | + //sending NG data is exist or send_rest_size > 0 | |
2498 | + if (send_disable) { | |
2499 | + //set end flag on | |
2500 | + session_data->end_flag = END_FLAG_ON; | |
2501 | + status = SORRYSERVER_DISCONNECT; | |
2502 | + } | |
2503 | + else { | |
2504 | + //sending possible data is exist | |
2505 | + if (send_possible) { | |
2506 | + status = CLIENT_CONNECTION_CHECK; | |
2507 | + } | |
2508 | + //sending possible data is not exist | |
2509 | + else { | |
2510 | + status = REALSERVER_RECV; | |
2511 | + } | |
2512 | + } | |
2513 | + } | |
2514 | + //sorry_flag is off | |
2515 | + else { | |
2516 | + //sending possible data is exist | |
2517 | + if (send_possible) { | |
2518 | + status = CLIENT_CONNECTION_CHECK; | |
2519 | + } | |
2520 | + //sending possible data is not exist | |
2521 | + else { | |
2522 | + status = REALSERVER_RECV; | |
2523 | + } | |
2524 | + } | |
2525 | + } | |
2526 | + } | |
2527 | + } catch (...) { | |
2528 | + status = FINALIZE; | |
2529 | + } | |
2530 | + | |
2531 | + return status; | |
2532 | +} | |
2533 | + | |
2534 | +//! call from realserver disconnect. use upstream thread and downstream thread | |
2535 | +//! @param[in] upstream and downstream thread id( check! one thread one event ) | |
2536 | +//! @param[in] disconnected realserver endpoint. | |
2537 | +//! @return session use EVENT mode | |
2538 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_disconnect( | |
2539 | + const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &rs_endpoint) | |
2540 | +{ | |
2541 | + EVENT_TAG status = FINALIZE; | |
2542 | + bool possible_flag = false; | |
2543 | + thread_data_ptr session_data; | |
2544 | + boost::asio::ip::tcp::endpoint endpoint; | |
2545 | + | |
2546 | + try { | |
2547 | + { | |
2548 | + boost::mutex::scoped_lock sclock(session_thread_data_map_mutex); | |
2549 | + | |
2550 | + session_thread_data_map_it session_thread_it = session_thread_data_map.find(thread_id); | |
2551 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
2552 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
2553 | + formatter % boost::this_thread::get_id(); | |
2554 | + putLogError(100120, formatter.str(), __FILE__, __LINE__); | |
2555 | + throw - 1; | |
2556 | + } | |
2557 | + | |
2558 | + session_data = session_thread_it->second; | |
2559 | + } | |
2560 | + | |
2561 | + endpoint = session_data->thread_division == THREAD_DIVISION_UP_STREAM ? session_data->client_endpoint_tcp | |
2562 | + : session_data->target_endpoint; | |
2563 | + receive_data_map_it receive_data_it = session_data->receive_data_map.find(endpoint); | |
2564 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
2565 | + return FINALIZE; | |
2566 | + } | |
2567 | + | |
2568 | + receive_data &recv_data = receive_data_it->second; | |
2569 | + | |
2570 | + //the data that can be sent possible is exist | |
2571 | + send_status_it it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), | |
2572 | + data_send_possible()); | |
2573 | + if (it != recv_data.send_status_list.end()) { | |
2574 | + possible_flag = true; | |
2575 | + } | |
2576 | + | |
2577 | + //up thread | |
2578 | + if (session_data->thread_division == THREAD_DIVISION_UP_STREAM) { | |
2579 | + //end flag is on | |
2580 | + if (session_data->end_flag == END_FLAG_ON) { | |
2581 | + status = CLIENT_RECV; | |
2582 | + } | |
2583 | + //end flag is off | |
2584 | + else { | |
2585 | + //sorryserver_switch_flag is on | |
2586 | + if (session_data->sorryserver_switch_flag == SORRYSERVER_SWITCH_FLAG_ON) { | |
2587 | + session_data->sorryserver_switch_flag = SORRYSERVER_SWITCH_FLAG_OFF; | |
2588 | + status = SORRYSERVER_SELECT; | |
2589 | + } | |
2590 | + //sorryserver_switch_flag is off | |
2591 | + else { | |
2592 | + //set end flag on | |
2593 | + session_data->end_flag = END_FLAG_ON; | |
2594 | + status = CLIENT_RECV; | |
2595 | + } | |
2596 | + } | |
2597 | + } | |
2598 | + //down thread | |
2599 | + else { | |
2600 | + if (session_data->end_flag == END_FLAG_ON) { | |
2601 | + status = CLIENT_DISCONNECT; | |
2602 | + } else { | |
2603 | + if (session_data->sorryserver_switch_flag == SORRYSERVER_SWITCH_FLAG_ON) { | |
2604 | + session_data->sorryserver_switch_flag = SORRYSERVER_SWITCH_FLAG_OFF; | |
2605 | + status = SORRYSERVER_RECV; | |
2606 | + } else { | |
2607 | + //set end flag on | |
2608 | + session_data->end_flag = END_FLAG_ON; | |
2609 | + status = CLIENT_DISCONNECT; | |
2610 | + } | |
2611 | + } | |
2612 | + | |
2613 | + //the data that can be sent possible is exist | |
2614 | + if (possible_flag) { | |
2615 | + status = CLIENT_CONNECTION_CHECK; | |
2616 | + } | |
2617 | + } | |
2618 | + } catch (...) { | |
2619 | + status = FINALIZE; | |
2620 | + } | |
2621 | + | |
2622 | + return status; | |
2623 | +} | |
2624 | + | |
2625 | +//! call from sorry server disconnect. use upstream thread and downstream thread | |
2626 | +//! @param[in] upstream and downstream thread id( check! one thread one event ) | |
2627 | +//! @param[in] disconnect sorryserver endpoint | |
2628 | +//! @return session use EVENT mode | |
2629 | +//! @return session use EVENT mode | |
2630 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_sorryserver_disconnect( | |
2631 | + const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &sorry_endpoint) | |
2632 | +{ | |
2633 | + EVENT_TAG status = FINALIZE; | |
2634 | + bool possible_flag = false; | |
2635 | + thread_data_ptr session_data; | |
2636 | + boost::asio::ip::tcp::endpoint endpoint; | |
2637 | + | |
2638 | + try { | |
2639 | + { | |
2640 | + boost::mutex::scoped_lock sclock(session_thread_data_map_mutex); | |
2641 | + | |
2642 | + session_thread_data_map_it session_thread_it = session_thread_data_map.find(thread_id); | |
2643 | + if (unlikely(session_thread_it == session_thread_data_map.end() || session_thread_it->second == NULL)) { | |
2644 | + boost::format formatter("Invalid thread id. thread id : %d."); | |
2645 | + formatter % boost::this_thread::get_id(); | |
2646 | + putLogError(100124, formatter.str(), __FILE__, __LINE__); | |
2647 | + throw - 1; | |
2648 | + } | |
2649 | + | |
2650 | + session_data = session_thread_it->second; | |
2651 | + } | |
2652 | + | |
2653 | + endpoint = session_data->thread_division == THREAD_DIVISION_UP_STREAM ? session_data->client_endpoint_tcp | |
2654 | + : session_data->target_endpoint; | |
2655 | + receive_data_map_it receive_data_it = session_data->receive_data_map.find(endpoint); | |
2656 | + if (unlikely(receive_data_it == session_data->receive_data_map.end())) { | |
2657 | + boost::format formatter("Invalid endpoint(%s). thread id: %d."); | |
2658 | + formatter % endpoint % boost::this_thread::get_id(); | |
2659 | + putLogError(100125, formatter.str(), __FILE__, __LINE__); | |
2660 | + throw - 1; | |
2661 | + } | |
2662 | + | |
2663 | + receive_data &recv_data = receive_data_it->second; | |
2664 | + | |
2665 | + //the data that can be sent possible is exist | |
2666 | + send_status_it it = find_if(recv_data.send_status_list.begin(), recv_data.send_status_list.end(), | |
2667 | + data_send_possible()); | |
2668 | + if (it != recv_data.send_status_list.end()) { | |
2669 | + possible_flag = true; | |
2670 | + } | |
2671 | + | |
2672 | + //up thread | |
2673 | + if (session_data->thread_division == THREAD_DIVISION_UP_STREAM) { | |
2674 | + //end flag is on | |
2675 | + if (session_data->end_flag == END_FLAG_ON) { | |
2676 | + status = CLIENT_RECV; | |
2677 | + } | |
2678 | + //end flag is off | |
2679 | + else { | |
2680 | + //realserver_switch_flag is on | |
2681 | + if (session_data->realserver_switch_flag == REALSERVER_SWITCH_FLAG_ON) { | |
2682 | + session_data->realserver_switch_flag = REALSERVER_SWITCH_FLAG_OFF; | |
2683 | + status = REALSERVER_SELECT; | |
2684 | + } | |
2685 | + //realserver_switch_flag is off | |
2686 | + else { | |
2687 | + //set end flag on | |
2688 | + session_data->end_flag = END_FLAG_ON; | |
2689 | + status = CLIENT_RECV; | |
2690 | + } | |
2691 | + } | |
2692 | + } | |
2693 | + //down thread | |
2694 | + else { | |
2695 | + if (session_data->end_flag == END_FLAG_ON) { | |
2696 | + status = CLIENT_DISCONNECT; | |
2697 | + } else { | |
2698 | + if (session_data->realserver_switch_flag == REALSERVER_SWITCH_FLAG_ON) { | |
2699 | + session_data->realserver_switch_flag = REALSERVER_SWITCH_FLAG_OFF; | |
2700 | + status = REALSERVER_RECV; | |
2701 | + } else { | |
2702 | + session_data->end_flag = END_FLAG_ON; | |
2703 | + status = CLIENT_DISCONNECT; | |
2704 | + } | |
2705 | + } | |
2706 | + | |
2707 | + //the data that can be sent possible is exist | |
2708 | + if (possible_flag) { | |
2709 | + status = CLIENT_CONNECTION_CHECK; | |
2710 | + } | |
2711 | + } | |
2712 | + } catch (...) { | |
2713 | + status = FINALIZE; | |
2714 | + } | |
2715 | + | |
2716 | + return status; | |
2717 | +} | |
2718 | + | |
2719 | +//! call from realserver disconnect. use upstream thread and downstream thread. | |
2720 | +//! @param[in] upstream and downstream thread id( check! one thread one event ) | |
2721 | +//! @param[in] disconnect realserver endpoint | |
2722 | +//! @return session use EVENT mode. | |
2723 | +protocol_module_base::EVENT_TAG protocol_module_simple::handle_realserver_close( | |
2724 | + const boost::thread::id thread_id, const boost::asio::ip::udp::endpoint &rs_endpoint) | |
2725 | +{ | |
2726 | + return STOP; | |
2727 | +} | |
2728 | + | |
2729 | +} | |
2730 | + | |
2731 | +extern "C" l7vs::protocol_module_base* | |
2732 | +create_module() | |
2733 | +{ | |
2734 | + return dynamic_cast<l7vs::protocol_module_base *>(new l7vs::protocol_module_simple()); | |
2735 | +} | |
2736 | + | |
2737 | +extern "C" void | |
2738 | +destroy_module(l7vs::protocol_module_base *in) | |
2739 | +{ | |
2740 | + delete in; | |
2741 | +} |
@@ -0,0 +1,288 @@ | ||
1 | +/* | |
2 | + * @file protocol_module_simple.h | |
3 | + * @brief protocol module simple header file. | |
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/mutex.hpp> | |
26 | +#include <boost/lexical_cast.hpp> | |
27 | +#include "http_protocol_module_base.h" | |
28 | + | |
29 | +#ifndef PROTOCOL_MODULE_SIMPLE_H | |
30 | +#define PROTOCOL_MODULE_SIMPLE_H | |
31 | + | |
32 | +#define MAX_OPTION_SIZE 128 | |
33 | +#define MAX_SIMPLE_MODULE_BUFFER_SIZE (8190 + MAX_BUFFER_SIZE) | |
34 | + | |
35 | +namespace l7vs | |
36 | +{ | |
37 | + | |
38 | +class protocol_module_simple : public http_protocol_module_base | |
39 | +{ | |
40 | +public: | |
41 | + enum SEND_STATUS_TAG { | |
42 | + SEND_OK = 0, | |
43 | + SEND_NG, | |
44 | + SEND_END, | |
45 | + SEND_CONTINUE | |
46 | + }; | |
47 | + struct edit_data { | |
48 | + std::string data; | |
49 | + size_t data_size; | |
50 | + size_t insert_posission; | |
51 | + size_t replace_size; | |
52 | + } ; | |
53 | + | |
54 | + struct send_status { | |
55 | + SEND_STATUS_TAG status; | |
56 | + size_t send_end_size; | |
57 | + size_t send_rest_size; | |
58 | + size_t send_possible_size; | |
59 | + size_t send_offset; | |
60 | + size_t unsend_size; | |
61 | + int edit_division; | |
62 | + boost::asio::ip::tcp::endpoint send_endpoint; | |
63 | + std::list<edit_data> edit_data_list; | |
64 | + }; | |
65 | + | |
66 | + struct receive_data { | |
67 | + char *receive_buffer; | |
68 | + char *receive_buffer1; | |
69 | + char *receive_buffer2; | |
70 | + size_t receive_buffer_max_size; | |
71 | + size_t receive_buffer_rest_size; | |
72 | + std::list<send_status> send_status_list; | |
73 | + receive_data() { | |
74 | + receive_buffer1 = NULL; | |
75 | + receive_buffer2 = NULL; | |
76 | + receive_buffer = NULL; | |
77 | + receive_buffer_max_size = 0; | |
78 | + receive_buffer_rest_size = 0; | |
79 | + } | |
80 | + ~receive_data() { | |
81 | + if (receive_buffer1 != NULL) { | |
82 | + delete [] receive_buffer1; | |
83 | + receive_buffer1 = NULL; | |
84 | + } | |
85 | + | |
86 | + if (receive_buffer2 != NULL) { | |
87 | + delete [] receive_buffer2; | |
88 | + receive_buffer2 = NULL; | |
89 | + } | |
90 | + | |
91 | + receive_buffer = NULL; | |
92 | + receive_buffer_max_size = 0; | |
93 | + receive_buffer_rest_size = 0; | |
94 | + } | |
95 | + }; | |
96 | + | |
97 | + | |
98 | + struct session_thread_data_simple { | |
99 | + boost::thread::id thread_id; | |
100 | + int thread_division; | |
101 | + boost::thread::id pair_thread_id; | |
102 | + std::map<boost::asio::ip::tcp::endpoint, receive_data> receive_data_map; | |
103 | + int end_flag; | |
104 | + int accept_end_flag; | |
105 | + int sorry_flag; | |
106 | + int sorryserver_switch_flag; | |
107 | + int realserver_switch_flag; | |
108 | + boost::asio::ip::tcp::endpoint target_endpoint; | |
109 | + boost::asio::ip::tcp::endpoint client_endpoint_tcp; | |
110 | + EVENT_TAG last_status; | |
111 | + }; | |
112 | + | |
113 | + typedef std::list<send_status>::iterator send_status_it; | |
114 | + typedef boost::shared_ptr<session_thread_data_simple> thread_data_ptr; | |
115 | + typedef std::map<boost::thread::id, thread_data_ptr>::iterator session_thread_data_map_it; | |
116 | + typedef std::map<boost::asio::ip::tcp::endpoint, receive_data>::iterator receive_data_map_it; | |
117 | +protected: | |
118 | + int forwarded_for; | |
119 | + boost:: array<char, MAX_OPTION_SIZE> sorry_uri ; | |
120 | + std::map<boost::thread::id, thread_data_ptr> session_thread_data_map; | |
121 | + boost::mutex session_thread_data_map_mutex; | |
122 | + | |
123 | +public: | |
124 | + static const std::string MODULE_NAME; | |
125 | + | |
126 | + static const int THREAD_DIVISION_UP_STREAM; | |
127 | + static const int THREAD_DIVISION_DOWN_STREAM; | |
128 | + | |
129 | + static const int END_FLAG_OFF; | |
130 | + static const int END_FLAG_ON; | |
131 | + | |
132 | + static const int ACCEPT_END_FLAG_OFF; | |
133 | + static const int ACCEPT_END_FLAG_ON; | |
134 | + | |
135 | + static const int SORRY_FLAG_ON; | |
136 | + static const int SORRY_FLAG_OFF; | |
137 | + | |
138 | + static const int SORRYSERVER_SWITCH_FLAG_OFF; | |
139 | + static const int SORRYSERVER_SWITCH_FLAG_ON; | |
140 | + | |
141 | + static const int REALSERVER_SWITCH_FLAG_OFF; | |
142 | + static const int REALSERVER_SWITCH_FLAG_ON; | |
143 | + | |
144 | + static const int EDIT_DIVISION_NO_EDIT; | |
145 | + static const int EDIT_DIVISION_EDIT; | |
146 | + | |
147 | + static const int FORWARDED_FOR_OFF; | |
148 | + static const int FORWARDED_FOR_ON; | |
149 | + | |
150 | + static const int COLLECT_STATS_OFF; | |
151 | + static const int COLLECT_STATS_ON; | |
152 | + | |
153 | +public: | |
154 | + protocol_module_simple(); | |
155 | + ~protocol_module_simple(); | |
156 | + | |
157 | + bool is_tcp(); | |
158 | + bool is_udp(); | |
159 | + void replication_interrupt(); | |
160 | + void initialize(rs_list_itr_func_type inlist_begin, | |
161 | + rs_list_itr_func_type inlist_end, | |
162 | + rs_list_itr_next_func_type inlist_next, | |
163 | + boost::function< void(void) > inlist_lock, | |
164 | + boost::function< void(void) > inlist_unlock); | |
165 | + void finalize(); | |
166 | + bool is_use_sorry(); | |
167 | + check_message_result check_parameter(const std::vector<std::string>& args); | |
168 | + check_message_result set_parameter(const std::vector<std::string>& args); | |
169 | + check_message_result add_parameter(const std::vector<std::string>& args); | |
170 | + void get_option_info(std::string &option); | |
171 | + void handle_rslist_update(); | |
172 | + void register_schedule(tcp_schedule_func_type inschedule); | |
173 | + void register_schedule(udp_schedule_func_type inschedule); | |
174 | + EVENT_TAG handle_session_initialize(const boost::thread::id up_thread_id, const boost::thread::id down_thread_id, const boost::asio::ip::tcp::endpoint &client_endpoint_tcp, const boost::asio::ip::udp::endpoint &client_endpoint_udp); | |
175 | + EVENT_TAG handle_session_finalize(const boost::thread::id up_thread_id, const boost::thread::id down_thread_id); | |
176 | + EVENT_TAG handle_accept(const boost::thread::id thread_id); | |
177 | + EVENT_TAG handle_client_recv(const boost::thread::id thread_id, const boost::array<char, MAX_BUFFER_SIZE>& recvbuffer, const size_t recvlen); | |
178 | + EVENT_TAG handle_realserver_select(const boost::thread::id thread_id, boost::asio::ip::tcp::endpoint &rs_endpoint); | |
179 | + EVENT_TAG handle_realserver_select(const boost::thread::id thread_id, boost::asio::ip::udp::endpoint &rs_endpoint, boost::array<char, MAX_BUFFER_SIZE>& sendbuffer, size_t &datalen); | |
180 | + EVENT_TAG handle_realserver_connect(const boost::thread::id thread_id, boost::array<char, MAX_BUFFER_SIZE>& sendbuffer, size_t &datalen); | |
181 | + EVENT_TAG handle_realserver_connection_fail(const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &rs_endpoint); | |
182 | + EVENT_TAG handle_realserver_send(const boost::thread::id thread_id); | |
183 | + EVENT_TAG handle_sorryserver_select(const boost::thread::id thread_id, boost::asio::ip::tcp::endpoint &sorry_endpoint); | |
184 | + EVENT_TAG handle_sorryserver_connect(const boost::thread::id thread_id, boost::array<char, MAX_BUFFER_SIZE>& sendbuffer, size_t &datalen); | |
185 | + EVENT_TAG handle_sorryserver_connection_fail(const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &sorry_endpoint); | |
186 | + EVENT_TAG handle_sorryserver_send(const boost::thread::id thread_id); | |
187 | + EVENT_TAG handle_realserver_recv(const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &rs_endpoint, const boost::array<char, MAX_BUFFER_SIZE>& recvbuffer, const size_t recvlen); | |
188 | + EVENT_TAG handle_realserver_recv(const boost::thread::id thread_id, const boost::asio::ip::udp::endpoint &rs_endpoint, const boost::array<char, MAX_BUFFER_SIZE>& recvbuffer, const size_t recvlen); | |
189 | + EVENT_TAG handle_sorryserver_recv(const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &sorry_endpoint, const boost::array<char, MAX_BUFFER_SIZE>& recvbuffer, const size_t recvlen); | |
190 | + EVENT_TAG handle_response_send_inform(const boost::thread::id thread_id); | |
191 | + EVENT_TAG handle_client_connection_check(const boost::thread::id thread_id, boost::array<char, MAX_BUFFER_SIZE>& sendbuffer, size_t &datalen); | |
192 | + EVENT_TAG handle_client_select(const boost::thread::id thread_id, boost::asio::ip::udp::endpoint &cl_endpoint, boost::array<char, MAX_BUFFER_SIZE>& sendbuffer, size_t &datalen); | |
193 | + EVENT_TAG handle_client_send(const boost::thread::id thread_id); | |
194 | + EVENT_TAG handle_client_disconnect(const boost::thread::id thread_id); | |
195 | + EVENT_TAG handle_sorry_enable(const boost::thread::id thread_id); | |
196 | + EVENT_TAG handle_sorry_disable(const boost::thread::id thread_id); | |
197 | + EVENT_TAG handle_realserver_disconnect(const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &rs_endpoint); | |
198 | + EVENT_TAG handle_sorryserver_disconnect(const boost::thread::id thread_id, const boost::asio::ip::tcp::endpoint &sorry_endpoint); | |
199 | + EVENT_TAG handle_realserver_close(const boost::thread::id thread_id, const boost::asio::ip::udp::endpoint &rs_endpoint); | |
200 | +}; | |
201 | + | |
202 | +inline bool operator < (const protocol_module_simple::edit_data &lref, const protocol_module_simple::edit_data &rref) | |
203 | +{ | |
204 | + return lref.insert_posission < rref.insert_posission; | |
205 | +} | |
206 | + | |
207 | +class data_send_possible | |
208 | +{ | |
209 | +public: | |
210 | + inline bool operator()(const protocol_module_simple::send_status &send_status) { | |
211 | + return send_status.status == protocol_module_simple::SEND_OK | |
212 | + && send_status.send_possible_size > 0; | |
213 | + } | |
214 | +}; | |
215 | + | |
216 | +class data_send_disable | |
217 | +{ | |
218 | +public: | |
219 | + inline bool operator()(const protocol_module_simple::send_status &send_status) { | |
220 | + return send_status.status == protocol_module_simple::SEND_NG | |
221 | + || send_status.send_rest_size > 0 ; | |
222 | + } | |
223 | +}; | |
224 | + | |
225 | +class data_send_continue | |
226 | +{ | |
227 | +public: | |
228 | + inline bool operator()(const protocol_module_simple::send_status &send_status) { | |
229 | + return send_status.status == protocol_module_simple::SEND_CONTINUE; | |
230 | + } | |
231 | +}; | |
232 | + | |
233 | +class data_send_ng | |
234 | +{ | |
235 | +public: | |
236 | + inline bool operator()(const protocol_module_simple::send_status &send_status) { | |
237 | + return send_status.status == protocol_module_simple::SEND_NG; | |
238 | + } | |
239 | +}; | |
240 | + | |
241 | +class data_send_ok | |
242 | +{ | |
243 | +public: | |
244 | + inline bool operator()(const protocol_module_simple::send_status &send_status) { | |
245 | + return send_status.status == protocol_module_simple::SEND_OK; | |
246 | + } | |
247 | +}; | |
248 | + | |
249 | +class data_send_repeated | |
250 | +{ | |
251 | +public: | |
252 | + inline bool operator()(const protocol_module_simple::send_status &send_status_first, | |
253 | + const protocol_module_simple::send_status &send_status_second) { | |
254 | + return send_status_first.status == protocol_module_simple::SEND_NG | |
255 | + || send_status_first.status == protocol_module_simple::SEND_CONTINUE; | |
256 | + } | |
257 | +}; | |
258 | + | |
259 | +class data_send_list_incorrect | |
260 | +{ | |
261 | +public: | |
262 | + inline bool operator()(const protocol_module_simple::send_status &send_status_first, | |
263 | + const protocol_module_simple::send_status &send_status_second) { | |
264 | + return (send_status_first.status == protocol_module_simple::SEND_OK | |
265 | + && send_status_first.send_rest_size > 0) | |
266 | + || (send_status_first.status == protocol_module_simple::SEND_CONTINUE) | |
267 | + || (send_status_first.status == protocol_module_simple::SEND_NG); | |
268 | + } | |
269 | +}; | |
270 | + | |
271 | +class rs_list_scoped_lock | |
272 | +{ | |
273 | +protected: | |
274 | + boost::function< void(void) > rs_list_unlock; | |
275 | +public: | |
276 | + rs_list_scoped_lock(boost::function< void(void) > inlist_lock, | |
277 | + boost::function< void(void) > inlist_unlock) { | |
278 | + inlist_lock(); | |
279 | + rs_list_unlock = inlist_unlock; | |
280 | + } | |
281 | + ~rs_list_scoped_lock() { | |
282 | + rs_list_unlock(); | |
283 | + } | |
284 | +}; | |
285 | +} | |
286 | + | |
287 | +#endif //PROTOCOL_MODULE_SIMPLE_H | |
288 | + |
@@ -0,0 +1,25 @@ | ||
1 | +AUTOMAKE_OPTIONS = foreign | |
2 | +L7VS_MODDIR = @l7vs_moddir@ | |
3 | +L7VS_INCLUDEDIR = @l7vs_includedir@ | |
4 | +MAX_BUFFER_SIZE = @l7vs_max_buffer_size@ | |
5 | +AM_CPPFLAGS = \ | |
6 | + -g -O2 -fno-strict-aliasing -Wall -Werror -fPIC -pthread \ | |
7 | + -I$(L7VS_INCLUDEDIR) \ | |
8 | + -DMAX_BUFFER_SIZE=$(MAX_BUFFER_SIZE) | |
9 | + | |
10 | +lib_LTLIBRARIES = \ | |
11 | + libsched_rnd.la | |
12 | + | |
13 | +libsched_rnd_la_SOURCES = \ | |
14 | + schedule_module_base.h \ | |
15 | + schedule_module_rnd.h \ | |
16 | + schedule_module_rnd.cpp | |
17 | + | |
18 | +libsched_rnd_la_LIBADD = -lrt -lboost_thread-mt | |
19 | + | |
20 | +install: | |
21 | + cp ./.libs/libsched_rnd.so ./.libs/sched_rnd.so && \ | |
22 | + $(INSTALL) -m 755 -d $(L7VS_MODDIR) | |
23 | + $(INSTALL) -m 755 -D \ | |
24 | + ./.libs/sched_rnd.so \ | |
25 | + $(L7VS_MODDIR) |
@@ -0,0 +1,24 @@ | ||
1 | +Sample source of schedule module for UltraMonkey-L7 . | |
2 | +This is random scheduler. | |
3 | + | |
4 | +== Files == | |
5 | +./schedule | |
6 | +configure.in | |
7 | +Makefile.am | |
8 | +schedule_module_rnd.cpp | |
9 | +schedule_module_rnd.h | |
10 | + | |
11 | +== Set up == | |
12 | +*please install um-l7 devel package before compile. | |
13 | + | |
14 | +cp -r ./schedule /path/to/develop | |
15 | +cd /path/to/develop/schedule | |
16 | +autoreconf -ifv | |
17 | +./configure | |
18 | +make | |
19 | +make install | |
20 | + | |
21 | +== How to use this module == | |
22 | +l7vsadm -A -t VIP:PORT -m PROTO_MOD -s rnd | |
23 | + | |
24 | + |
@@ -0,0 +1,89 @@ | ||
1 | +AC_PREREQ(2.59) | |
2 | +AC_INIT(l7vsd) | |
3 | +PACKAGENAME=ultramonkeyl7-mod-random-1.0.0 | |
4 | +VERSION=1.0.0 | |
5 | + | |
6 | +AM_INIT_AUTOMAKE($PACKAGENAME, $VERSION, no-define ) | |
7 | +AC_CONFIG_SRCDIR([config.h.in]) | |
8 | +AC_CONFIG_HEADER([config.h]) | |
9 | + | |
10 | +# Checks for programs. | |
11 | +AC_PROG_CXX | |
12 | +AC_PROG_LIBTOOL | |
13 | +AC_PROG_CPP | |
14 | +AC_PROG_INSTALL | |
15 | +AC_PROG_LN_S | |
16 | +AC_PROG_MAKE_SET | |
17 | + | |
18 | +# Checks for libraries. | |
19 | +AC_CHECK_LIB(dl, dlopen) | |
20 | +AC_CHECK_LIB(log4cxx, main, :, | |
21 | + [AC_MSG_ERROR( l7vsd require log4cxx library. )] ) | |
22 | +AC_CHECK_LIB(rt, main, :, | |
23 | + [AC_MSG_ERROR( l7vsd require rt library. )] ) | |
24 | +AC_CHECK_LIB(boost_thread-mt, main, :, | |
25 | + [AC_MSG_ERROR( l7vsd require boost library. )] ) | |
26 | +AC_CHECK_LIB(boost_system-mt, main, :, | |
27 | + [AC_MSG_ERROR( l7vsd require boost library. )] ) | |
28 | + | |
29 | +# Checks for header files. | |
30 | +AC_CHECK_HEADERS([limits.h unistd.h]) | |
31 | + | |
32 | +# Checks for typedefs, structures, and compiler characteristics. | |
33 | +AC_HEADER_STDBOOL | |
34 | +AC_C_CONST | |
35 | +AC_C_INLINE | |
36 | +AC_TYPE_SIZE_T | |
37 | +AC_STRUCT_TM | |
38 | + | |
39 | +# Checks for library functions. | |
40 | +AC_HEADER_STDC | |
41 | +AC_FUNC_MKTIME | |
42 | +AC_FUNC_STRFTIME | |
43 | +AC_CHECK_FUNCS([gethostname localtime_r memset]) | |
44 | + | |
45 | +# application-specific option | |
46 | +if test `uname -m` == "x86_64"; then | |
47 | + AC_SUBST( libdir, [/usr/lib64] ) | |
48 | +else | |
49 | + AC_SUBST( libdir, [/usr/lib] ) | |
50 | + AC_SUBST( CXXFLAGS, -march=i686 ) | |
51 | +fi | |
52 | +AC_SUBST( includedir, [/usr/include] ) | |
53 | + | |
54 | +AC_ARG_WITH( | |
55 | + l7vs-moddir, | |
56 | + [ --with-l7vs-moddir=DIR l7vs module is to be installed in DIR. | |
57 | + [default=LIBDIR/l7vs] ], | |
58 | + [ l7vs_moddir="$withval" ], | |
59 | + [ l7vs_moddir="${libdir}/l7vs" ] | |
60 | +) | |
61 | + | |
62 | +AC_ARG_WITH( | |
63 | + l7vs-includedir, | |
64 | + [ --with-l7vs-includedir=DIR l7vs headerfile is to be installed in DIR. | |
65 | + [default=INCLUDEDIR/l7vs] ], | |
66 | + [ l7vs_includedir="$withval" ], | |
67 | + [ l7vs_includedir="${includedir}/l7vs" ] | |
68 | +) | |
69 | + | |
70 | +AC_ARG_WITH( | |
71 | + l7vs-buffer-size, | |
72 | + [ --with-l7vs-buffer-size=NUM l7vsd using heap buffer size. | |
73 | + [default=4096] ], | |
74 | + [ l7vs_max_buffer_size="$withval" ], | |
75 | + [ l7vs_max_buffer_size=4096 ] | |
76 | +) | |
77 | + | |
78 | + | |
79 | +AC_SUBST(CC,g++) | |
80 | +AC_SUBST(exec_prefix, [/usr] ) | |
81 | +AC_SUBST(l7vs_moddir) | |
82 | +AC_SUBST(l7vs_includedir) | |
83 | +AC_SUBST(l7vs_max_buffer_size) | |
84 | +AC_SUBST(MANDIR) | |
85 | +AC_SUBST(ultramonkeyl7_version,ultramonkeyl7-$VERSION) | |
86 | + | |
87 | +AC_CONFIG_FILES([Makefile]) | |
88 | + | |
89 | +AC_OUTPUT |
@@ -0,0 +1,280 @@ | ||
1 | +/* | |
2 | + * @file schedule_module_rnd.cpp | |
3 | + * @brief shared object schedule module 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 | +#include "schedule_module_rnd.h" | |
25 | +#include <boost/format.hpp> | |
26 | + | |
27 | +#include "utility.h" | |
28 | + | |
29 | +namespace l7vs | |
30 | +{ | |
31 | + | |
32 | +//! constructor | |
33 | +schedule_module_random::schedule_module_random() : schedule_module_base("rnd") | |
34 | +{ | |
35 | +} | |
36 | + | |
37 | +//! destructor | |
38 | +schedule_module_random::~schedule_module_random() {} | |
39 | + | |
40 | +//! initialize function | |
41 | +void schedule_module_random::initialize() | |
42 | +{ | |
43 | + if (likely(!getloglevel.empty())) { | |
44 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
45 | + if (likely(!putLogDebug.empty())) { | |
46 | + putLogDebug(200000, "Function in : schedule_module_random::initialize", __FILE__, __LINE__); | |
47 | + } | |
48 | + } | |
49 | + } | |
50 | + | |
51 | + boost::asio::ip::tcp::endpoint tcp_local_endpoint ; | |
52 | + boost::asio::ip::udp::endpoint udp_local_endpoint ; | |
53 | + | |
54 | + tcp_endpoint = tcp_local_endpoint ; | |
55 | + udp_endpoint = udp_local_endpoint ; | |
56 | + | |
57 | + if (likely(!putLogInfo.empty())) { | |
58 | + putLogInfo(200000, "Saved endpoint was initialized.", __FILE__, __LINE__); | |
59 | + } | |
60 | + | |
61 | + if (likely(!getloglevel.empty())) { | |
62 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
63 | + if (likely(!putLogDebug.empty())) { | |
64 | + putLogDebug(200001, "Function out : schedule_module_random::initialize", __FILE__, __LINE__); | |
65 | + } | |
66 | + } | |
67 | + } | |
68 | +} | |
69 | + | |
70 | +//! tcp protocol support check | |
71 | +//! @return tcp support is true | |
72 | +//! @return tcp not-support is false | |
73 | +bool schedule_module_random::is_tcp() | |
74 | +{ | |
75 | + return true; | |
76 | +} | |
77 | + | |
78 | +//! udp protocol support check | |
79 | +//! @return udp support is true | |
80 | +//! @return udp not-support is false | |
81 | +bool schedule_module_random::is_udp() | |
82 | +{ | |
83 | + return true; | |
84 | +} | |
85 | + | |
86 | +//! handle schedule called then schedule function for TCP/IP endpoint | |
87 | +//! @param[in] thread id | |
88 | +//! @param[in] list iterator first function object | |
89 | +//! @param[in] list iterator last function object | |
90 | +//! @param[in] list iterator next function object | |
91 | +//! @param[out] scheduled TCP/IP endpoint | |
92 | +void schedule_module_random::handle_schedule( | |
93 | + boost::thread::id thread_id, | |
94 | + rslist_iterator_begin_func_type inlist_begin, | |
95 | + rslist_iterator_end_func_type inlist_end, | |
96 | + rslist_iterator_next_func_type inlist_next, | |
97 | + boost::asio::ip::tcp::endpoint &outendpoint) | |
98 | +{ | |
99 | + if (likely(!getloglevel.empty())) { | |
100 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
101 | + if (likely(!putLogDebug.empty())) { | |
102 | + putLogDebug(200002, "Function in : schedule_module_random::handle_schedule", __FILE__, __LINE__); | |
103 | + } | |
104 | + } | |
105 | + } | |
106 | + | |
107 | + boost::asio::ip::tcp::endpoint tcp_local_endpoint ; | |
108 | + rslist_type::iterator itr; | |
109 | + std::string buf; | |
110 | + int loop; | |
111 | + std::vector<boost::asio::ip::tcp::endpoint> tmp_list; | |
112 | + | |
113 | + //! set clear data as NULL | |
114 | + outendpoint = tcp_local_endpoint; | |
115 | + | |
116 | + if (unlikely(inlist_begin.empty() || inlist_end.empty() || inlist_next.empty())) { | |
117 | + //! invalid iterator function | |
118 | + if (likely(!putLogFatal.empty())) { | |
119 | + putLogFatal(200000, "Iterator function is empty.", __FILE__, __LINE__); | |
120 | + } | |
121 | + goto END; | |
122 | + } | |
123 | + | |
124 | + //! Debug log | |
125 | + if (likely(!getloglevel.empty())) { | |
126 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
127 | + if (likely(!putLogDebug.empty())) { | |
128 | + for (loop = 1, itr = inlist_begin(); itr != inlist_end(); itr = inlist_next(itr), loop++) { | |
129 | + buf = boost::io::str(boost::format("realserver[%d] : %s:%d weight(%d)") | |
130 | + % loop | |
131 | + % itr->tcp_endpoint.address() | |
132 | + % itr->tcp_endpoint.port() | |
133 | + % itr->weight); | |
134 | + putLogDebug(200003, buf, __FILE__, __LINE__); | |
135 | + } | |
136 | + } | |
137 | + } | |
138 | + } | |
139 | + //! Debug log END | |
140 | + | |
141 | + for (itr = inlist_begin(); itr != inlist_end(); itr = inlist_next(itr)) { | |
142 | + // pure random | |
143 | + /* | |
144 | + if (itr->weight > 0) { | |
145 | + tmp_list.push_back(itr->tcp_endpoint); | |
146 | + } | |
147 | + */ | |
148 | + // rs1 weight=1 ,rs2 weight=2 | |
149 | + // hit % => rs1:33% rs2:66% | |
150 | + for(int i=0; i < itr->weight; i++){ | |
151 | + tmp_list.push_back(itr->tcp_endpoint); | |
152 | + } | |
153 | + } | |
154 | + | |
155 | + if (unlikely(tmp_list.empty())) { | |
156 | + //! no data | |
157 | + if (likely(!putLogError.empty())) { | |
158 | + putLogError(200000, "There is no realserver on list.", __FILE__, __LINE__); | |
159 | + } | |
160 | + goto END; | |
161 | + } | |
162 | + //! set endpoind | |
163 | + outendpoint = tmp_list.at(rand() % tmp_list.size()); | |
164 | + | |
165 | +END: | |
166 | + if (likely(!getloglevel.empty())) { | |
167 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
168 | + if (likely(!putLogDebug.empty())) { | |
169 | + putLogDebug(200006, "Function out : schedule_module_random::handle_schedule", __FILE__, __LINE__); | |
170 | + } | |
171 | + } | |
172 | + } | |
173 | +} | |
174 | + | |
175 | +//! handle schedule calls then schedule function for UDP endpoint | |
176 | +//! @param[in] thread id | |
177 | +//! @param[in] list iterator first function object | |
178 | +//! @param[in] list iterator last function object | |
179 | +//! @param[in] list iterator next function object | |
180 | +//! @param[out] scheduled UDP endpoint | |
181 | +void schedule_module_random::handle_schedule( | |
182 | + boost::thread::id thread_id, | |
183 | + rslist_iterator_begin_func_type inlist_begin, | |
184 | + rslist_iterator_end_func_type inlist_end, | |
185 | + rslist_iterator_next_func_type inlist_next, | |
186 | + boost::asio::ip::udp::endpoint &outendpoint) | |
187 | +{ | |
188 | + if (likely(!getloglevel.empty())) { | |
189 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
190 | + if (likely(!putLogDebug.empty())) { | |
191 | + putLogDebug(200007, "Function in : schedule_module_random::handle_schedule", __FILE__, __LINE__); | |
192 | + } | |
193 | + } | |
194 | + } | |
195 | + | |
196 | + boost::asio::ip::udp::endpoint udp_local_endpoint ; | |
197 | + rslist_type::iterator itr; | |
198 | + std::string buf; | |
199 | + int loop; | |
200 | + std::vector<boost::asio::ip::udp::endpoint> tmp_list; | |
201 | + | |
202 | + //! set clear data as NULL | |
203 | + outendpoint = udp_local_endpoint; | |
204 | + | |
205 | + if (unlikely(inlist_begin.empty() || inlist_end.empty() || inlist_next.empty())) { | |
206 | + //! invalid iterator function | |
207 | + if (likely(!putLogFatal.empty())) { | |
208 | + putLogFatal(200001, "Iterator function is empty.", __FILE__, __LINE__); | |
209 | + } | |
210 | + goto END; | |
211 | + } | |
212 | + | |
213 | + //! Debug log | |
214 | + if (likely(!getloglevel.empty())) { | |
215 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
216 | + if (likely(!putLogDebug.empty())) { | |
217 | + for (loop = 1, itr = inlist_begin(); itr != inlist_end(); itr = inlist_next(itr), loop++) { | |
218 | + buf = boost::io::str(boost::format("realserver[%d] : %s:%d weight(%d)") | |
219 | + % loop | |
220 | + % itr->udp_endpoint.address() | |
221 | + % itr->udp_endpoint.port() | |
222 | + % itr->weight); | |
223 | + putLogDebug(200008, buf, __FILE__, __LINE__); | |
224 | + } | |
225 | + } | |
226 | + } | |
227 | + } | |
228 | + //! Debug log END | |
229 | + | |
230 | + for (itr = inlist_begin(); itr != inlist_end(); itr = inlist_next(itr)) { | |
231 | + // pure random | |
232 | + /* | |
233 | + if (itr->weight > 0) { | |
234 | + tmp_list.push_back(itr->udp_endpoint); | |
235 | + } | |
236 | + */ | |
237 | + // rs1 weight=1 ,rs2 weight=2 | |
238 | + // hit % => rs1:33% rs2:66% | |
239 | + for(int i=0; i < itr->weight; i++){ | |
240 | + tmp_list.push_back(itr->udp_endpoint); | |
241 | + } | |
242 | + } | |
243 | + if (unlikely(tmp_list.empty())) { | |
244 | + //! no data | |
245 | + if (likely(!putLogError.empty())) { | |
246 | + putLogError(200000, "There is no realserver on list.", __FILE__, __LINE__); | |
247 | + } | |
248 | + goto END; | |
249 | + } | |
250 | + | |
251 | + //! set endpoind | |
252 | + outendpoint = tmp_list.at(rand() % tmp_list.size()); | |
253 | + | |
254 | +END: | |
255 | + if (likely(!getloglevel.empty())) { | |
256 | + if (unlikely(LOG_LV_DEBUG == getloglevel())) { | |
257 | + if (likely(!putLogDebug.empty())) { | |
258 | + putLogDebug(200011, "Function out : schedule_module_random::handle_schedule", __FILE__, __LINE__); | |
259 | + } | |
260 | + } | |
261 | + } | |
262 | +} | |
263 | + | |
264 | +//! replication interval interrupt | |
265 | +//! timer thread call this function. from virtualservice. | |
266 | +void schedule_module_random::replication_interrupt() {} | |
267 | + | |
268 | +} //namespace l7vs | |
269 | + | |
270 | +extern "C" l7vs::schedule_module_base* | |
271 | +create_module() | |
272 | +{ | |
273 | + return dynamic_cast<l7vs::schedule_module_base *>(new l7vs::schedule_module_random()); | |
274 | +} | |
275 | + | |
276 | +extern "C" void | |
277 | +destroy_module(l7vs::schedule_module_base *in) | |
278 | +{ | |
279 | + delete in; | |
280 | +} |
@@ -0,0 +1,88 @@ | ||
1 | +/* | |
2 | + * @file schedule_module_rnd.h | |
3 | + * @brief shared object schedule module 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 | +#ifndef SCHEDULE_MODULE_RND_H | |
25 | +#define SCHEDULE_MODULE_RND_H | |
26 | + | |
27 | +#include "schedule_module_base.h" | |
28 | + | |
29 | +namespace l7vs | |
30 | +{ | |
31 | + | |
32 | +class schedule_module_random : public schedule_module_base | |
33 | +{ | |
34 | +protected: | |
35 | + boost::asio::ip::tcp::endpoint tcp_endpoint ; | |
36 | + boost::asio::ip::udp::endpoint udp_endpoint ; | |
37 | +public: | |
38 | + //! constructor | |
39 | + schedule_module_random(); | |
40 | + //! destructor | |
41 | + ~schedule_module_random(); | |
42 | + | |
43 | + //! initialize function | |
44 | + void initialize(); | |
45 | + | |
46 | + //! tcp protocol support check | |
47 | + //! @return tcp support is true | |
48 | + //! @return tcp not-support is false | |
49 | + bool is_tcp(); | |
50 | + //! udp protocol support check | |
51 | + //! @return udp support is true | |
52 | + //! @return udp not-support is false | |
53 | + bool is_udp(); | |
54 | + | |
55 | + //! handle schedule called then schedule function for TCP/IP endpoint | |
56 | + //! @param[in] thread id | |
57 | + //! @param[in] list iterator first function object | |
58 | + //! @param[in] list iterator last function object | |
59 | + //! @param[in] list iterator next function object | |
60 | + //! @param[out] scheduled TCP/IP endpoint | |
61 | + void handle_schedule( | |
62 | + boost::thread::id thread_id, | |
63 | + rslist_iterator_begin_func_type inlist_begin, | |
64 | + rslist_iterator_end_func_type inlist_end, | |
65 | + rslist_iterator_next_func_type inlist_next, | |
66 | + boost::asio::ip::tcp::endpoint &outendpoint); | |
67 | + | |
68 | + //! handle schedule calls then schedule function for UDP endpoint | |
69 | + //! @param[in] thread id | |
70 | + //! @param[in] list iterator first function object | |
71 | + //! @param[in] list iterator last function object | |
72 | + //! @param[in] list iterator next function object | |
73 | + //! @param[out] scheduled UDP endpoint | |
74 | + void handle_schedule( | |
75 | + boost::thread::id thread_id, | |
76 | + rslist_iterator_begin_func_type inlist_begin, | |
77 | + rslist_iterator_end_func_type inlist_end, | |
78 | + rslist_iterator_next_func_type inlist_next, | |
79 | + boost::asio::ip::udp::endpoint &outendpoint); | |
80 | + | |
81 | + //! replication interval interrupt | |
82 | + //! timer thread call this function. from virtualservice. | |
83 | + void replication_interrupt(); | |
84 | +}; | |
85 | + | |
86 | +} //namespace l7vs | |
87 | + | |
88 | +#endif //SCHEDULE_MODULE_RND_H |
@@ -1,5 +1,6 @@ | ||
1 | 1 | %define l7vs_moddir %{_libdir}/l7vs |
2 | 2 | %define l7vs_logdir %{_localstatedir}/log/l7vs |
3 | +%define l7vs_includedir %{_includedir}/l7vs | |
3 | 4 | %define l7vsadm_sockdir %{_localstatedir}/run/l7vs |
4 | 5 | %define l7vs_maxvs 64 |
5 | 6 |
@@ -14,13 +15,35 @@ Source0: %{name}-%{version}.tar.gz | ||
14 | 15 | BuildRoot: %{_tmppath}/%{name}-%{version}-root |
15 | 16 | BuildRequires: glib2-devel |
16 | 17 | AutoReqProv: no |
18 | +Requires: boost >= 1.41.0 | |
19 | +Requires: apache-log4cxx >= 0.10.0 | |
20 | +Requires: apr | |
21 | +Requires: apr-util | |
22 | +Requires: openssl | |
23 | +Requires: net-snmp | |
24 | +Requires: perl | |
25 | +Requires: perl-libwww-perl | |
26 | +Requires: perl-Crypt-SSLeay | |
27 | +Requires: perl-Net-SSLeay | |
28 | +Requires: perl-IO-Socket-SSL | |
29 | +Requires: perl-IO-Socket-INET6 | |
17 | 30 | |
18 | 31 | %define hb2_tempdir /usr/share/doc/%{name}-%{version}-%{release}/heartbeat-ra |
19 | 32 | %define mibs_tempdir /usr/share/doc/%{name}-%{version}-%{release}/mibs |
33 | +%define moduledevel_tempdir /usr/share/doc/%{name}-%{version}-%{release}/moduledevel | |
20 | 34 | |
21 | 35 | %description |
22 | 36 | Layer-7 load balancing daemon |
23 | 37 | |
38 | +%package devel | |
39 | +Summary: Header files for UltraMonkeyl7's module | |
40 | +Group: Development/Libraries | |
41 | +Requires: %{name} = %{version}-%{release} | |
42 | + | |
43 | +%description devel | |
44 | +This is the development package that provides header files | |
45 | +for UltraMonkeyl7's module. | |
46 | + | |
24 | 47 | %prep |
25 | 48 | %setup -q |
26 | 49 |
@@ -41,6 +64,9 @@ mkdir -p ${RPM_BUILD_ROOT}%{l7vs_logdir} | ||
41 | 64 | mkdir -p ${RPM_BUILD_ROOT}%{l7vsadm_sockdir} |
42 | 65 | mkdir -p ${RPM_BUILD_ROOT}%{hb2_tempdir} |
43 | 66 | mkdir -p ${RPM_BUILD_ROOT}%{mibs_tempdir} |
67 | +mkdir -p ${RPM_BUILD_ROOT}%{moduledevel_tempdir} | |
68 | +mkdir -p ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample | |
69 | +mkdir -p ${RPM_BUILD_ROOT}%{l7vs_includedir} | |
44 | 70 | |
45 | 71 | # bin |
46 | 72 | install -c -m 755 -D l7vsd/src/l7vsd ${RPM_BUILD_ROOT}%{_sbindir}/l7vsd |
@@ -80,6 +106,34 @@ install -c -m 755 -D doc/heartbeat-ra/VIPcheck ${RPM_BUILD_ROOT}%{hb2_tempdir}/V | ||
80 | 106 | # mib file |
81 | 107 | install -c -m 644 -D doc/mibs/ULTRAMONKEY-L7-MIB.txt ${RPM_BUILD_ROOT}%{mibs_tempdir}/ULTRAMONKEY-L7-MIB.txt |
82 | 108 | |
109 | +# header for devel | |
110 | +install -c -m 644 -D l7vsd/include/protocol_module_base.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/protocol_module_base.h | |
111 | +install -c -m 644 -D l7vsd/include/schedule_module_base.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/schedule_module_base.h | |
112 | +install -c -m 644 -D l7vsd/include/module_base.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/module_base.h | |
113 | +install -c -m 644 -D l7vsd/include/utility.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/utility.h | |
114 | +install -c -m 644 -D l7vsd/include/logger.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/logger.h | |
115 | +install -c -m 644 -D l7vsd/include/logger_enum.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/logger_enum.h | |
116 | +install -c -m 644 -D l7vsd/include/trapmessage.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/trapmessage.h | |
117 | +install -c -m 644 -D l7vsd/include/error_code.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/error_code.h | |
118 | +install -c -m 644 -D l7vsd/include/atomic.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/atomic.h | |
119 | +install -c -m 644 -D l7vsd/include/wrlock.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/wrlock.h | |
120 | +install -c -m 644 -D l7vsd/include/replication.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/replication.h | |
121 | +install -c -m 644 -D l7vsd/include/realserver.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/realserver.h | |
122 | +install -c -m 644 -D l7vsd/include/realserver_element.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/realserver_element.h | |
123 | +install -c -m 644 -D l7vsd/include/endpoint.h ${RPM_BUILD_ROOT}%{l7vs_includedir}/endpoint.h | |
124 | +install -c -m 644 -D doc/moduledevel/sample/protocol/README ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/protocol/README | |
125 | +install -c -m 644 -D doc/moduledevel/sample/protocol/Makefile.am ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/protocol/Makefile.am | |
126 | +install -c -m 644 -D doc/moduledevel/sample/protocol/configure.in ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/protocol/configure.in | |
127 | +install -c -m 644 -D doc/moduledevel/sample/protocol/http_protocol_module_base.cpp ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/protocol/http_protocol_module_base.cpp | |
128 | +install -c -m 644 -D doc/moduledevel/sample/protocol/http_protocol_module_base.h ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/protocol/http_protocol_module_base.h | |
129 | +install -c -m 644 -D doc/moduledevel/sample/protocol/protocol_module_simple.cpp ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/protocol/protocol_module_simple.cpp | |
130 | +install -c -m 644 -D doc/moduledevel/sample/protocol/protocol_module_simple.h ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/protocol/protocol_module_simple.h | |
131 | +install -c -m 644 -D doc/moduledevel/sample/schedule/README ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/schedule/README | |
132 | +install -c -m 644 -D doc/moduledevel/sample/schedule/Makefile.am ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/schedule/Makefile.am | |
133 | +install -c -m 644 -D doc/moduledevel/sample/schedule/configure.in ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/schedule/configure.in | |
134 | +install -c -m 644 -D doc/moduledevel/sample/schedule/schedule_module_rnd.cpp ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/schedule/schedule_module_rnd.cpp | |
135 | +install -c -m 644 -D doc/moduledevel/sample/schedule/schedule_module_rnd.h ${RPM_BUILD_ROOT}%{moduledevel_tempdir}/sample/schedule/schedule_module_rnd.h | |
136 | + | |
83 | 137 | %clean |
84 | 138 | rm -rf $RPM_BUILD_ROOT |
85 | 139 |
@@ -112,9 +166,30 @@ fi | ||
112 | 166 | %dir %{mibs_tempdir} |
113 | 167 | %config(noreplace) %{mibs_tempdir}/* |
114 | 168 | |
169 | +%files devel | |
170 | +%defattr(-, root, root, 0755) | |
171 | +%dir %{_includedir}/l7vs | |
172 | +%{_includedir}/l7vs/protocol_module_base.h | |
173 | +%{_includedir}/l7vs/schedule_module_base.h | |
174 | +%{_includedir}/l7vs/module_base.h | |
175 | +%{_includedir}/l7vs/utility.h | |
176 | +%{_includedir}/l7vs/logger.h | |
177 | +%{_includedir}/l7vs/logger_enum.h | |
178 | +%{_includedir}/l7vs/trapmessage.h | |
179 | +%{_includedir}/l7vs/error_code.h | |
180 | +%{_includedir}/l7vs/atomic.h | |
181 | +%{_includedir}/l7vs/wrlock.h | |
182 | +%{_includedir}/l7vs/replication.h | |
183 | +%{_includedir}/l7vs/realserver.h | |
184 | +%{_includedir}/l7vs/realserver_element.h | |
185 | +%{_includedir}/l7vs/endpoint.h | |
186 | +%dir %{moduledevel_tempdir} | |
187 | +%{moduledevel_tempdir}/* | |
188 | + | |
115 | 189 | %changelog |
116 | 190 | * Sat Sep 8 2012 HIBARI Michiro <l05102@shibaura-it.ac.jp> 3.1.0-devel |
117 | 191 | - Update for 3.1.0-devel |
192 | +- Change spec file for generate devel package. | |
118 | 193 | |
119 | 194 | * Fri Aug 31 2012 Hiroaki Nakano <nakano.hiroaki@nttcom.co.jp> 3.0.4-2 |
120 | 195 | - Update for 3.0.4-2 |