OSDN Git Service

Fixed chkconfig option
[ultramonkey-l7/ultramonkey-l7-v2.git] / src / lsock.c
1 /*!
2  * @file lsock.c
3  * @bref listen socket control.
4  *
5  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
6  * Copyright (C) 2005  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 <sys/types.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <netinet/tcp.h>
29 #include <arpa/inet.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <assert.h>
33 #include <glib.h>
34 #include <errno.h>
35 #include "logger_wrapper.h"
36 #include "l7vs.h"
37 #include "l7vs_iomuxlist.h"
38 #include "l7vs_lsock.h"
39 #include "l7vs_module.h"
40 #include "l7vs_conn.h"
41 #include "l7vs_service.h"
42 #include "l7vs_sched.h"
43
44 /* static functions */
45 static int      l7vs_lsock_accept(struct l7vs_lsock *lsock);
46 static void     l7vs_lsock_table_add(struct l7vs_lsock *lsock);
47 static void     l7vs_lsock_table_remove(struct l7vs_lsock *lsock);
48 static gint     l7vs_lsock_addr_cmp(gconstpointer a, gconstpointer b);
49 static int      l7vs_lsock_callback(struct l7vs_iomux *iom );
50
51 //! l7vs_lsock list 
52 static GList *l7vs_lsock_list;
53
54 /*!
55  * inner function of fini.
56  * all element free.
57  * @param[in]   void
58  * @return      void
59  */
60 void    freeAllList( gpointer data, gpointer userdata ){
61         struct l7vs_lsock*      lsock = (struct l7vs_lsock*)data;
62
63         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
64                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,2,
65                                      "lsock in_fuction freeAllList : lsock=%p",
66                                       lsock);
67         }
68
69         free( lsock );
70 }
71
72 /*!
73  * initialize functions
74  * @param[in]   void
75  * @return      everydays zero.
76  */
77 int
78 l7vs_lsock_init(void)
79 {       
80         if(l7vs_lsock_list == NULL )
81         {       
82                 if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
83                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,3,
84                                      "lsock in_fuction int l7vs_lsock_init(void) : l7vs_lsock_list == NULL return 0");
85                 }
86                 return 0;
87         }
88         g_list_foreach( l7vs_lsock_list, freeAllList, NULL );
89         g_list_free( l7vs_lsock_list );
90         l7vs_lsock_list = NULL;
91
92         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
93                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,4,
94                                 "lsock in_fuction int l7vs_lsock_init(void) : l7vs_lsock_list == NULL return 0");
95         }
96         return 0;
97 }
98
99 /*!
100  * finalize function.
101  *  free list element memory.
102  *  drop list memory.
103  * @param[in]   void
104  * @return      void
105  */
106 void
107 l7vs_lsock_fini(void)
108 {
109         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
110                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,5,
111                                 "lsock in_fuction int l7vs_lsock_fini(void) : free l7vs_lsock_list = %p",
112                                 l7vs_lsock_list);
113         }
114
115         g_list_foreach( l7vs_lsock_list, freeAllList, NULL );
116         g_list_free( l7vs_lsock_list );
117         l7vs_lsock_list = NULL;
118 }
119 /*!
120  * look up socket
121  * if target soket have link list then return having socket.
122  * else create new socket to return.
123  * @param[in]   sin     socket address struct( if ipv6 may be change this struct ) 
124  * @param[in]   proto   TCS/UDP select.
125  * @param[in]   backlog 
126  */
127 struct l7vs_lsock *
128 l7vs_lsock_get(struct sockaddr_in *sin, uint8_t proto, int backlog)
129 {
130         struct l7vs_lsock *lsock;
131         int stype;
132         int ret;
133         int on = 1;
134
135         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
136                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,20,
137                     "in_fuction:  struct l7vs_lsock * l7vs_lsock_get(struct sockaddr_in *sin, uint8_t proto, int backlog)"
138                         "*sin =%p :proto = %d :backlog = %d :",
139                                 sin,proto,backlog);
140         }
141
142         if(sin == NULL )
143         {
144                 return NULL;
145         }
146
147         lsock = l7vs_lsock_table_lookup(sin, proto);
148         if (lsock != NULL) {
149                 lsock->refcnt++;
150                 if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
151                         char lsock_str[DEBUG_STR_LEN] = {0};
152                         l7vs_lsock_c_str(lsock_str, lsock);
153                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,21,
154                                         "table look up: lsock=%s",
155                                         lsock_str);
156                 }
157                 return lsock;
158         }
159                                                          
160         switch (proto) {
161         case IPPROTO_TCP:
162                 stype = SOCK_STREAM;
163                 break;
164         case IPPROTO_UDP:
165                 stype = SOCK_DGRAM;
166                 break;
167         default:
168                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SYSTEM_SOCKET,21, "Protocol number should be"
169                                           " TCP or UDP (%d)",
170                                           proto);
171                 return NULL;
172         }
173
174         lsock = (struct l7vs_lsock *)calloc(1, sizeof(*lsock));
175         if (lsock == NULL) {
176                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SYSTEM_MEMORY,14, "Could not allocate lsock");
177                 return lsock;
178         }
179         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
180                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,6,
181                                         "in function l7vs_lsock_get: allocate memory"
182                                         " : size=%zu ,pointer=%p",
183                                         sizeof(*lsock),lsock);
184         }
185
186         lsock->iom = l7vs_iomux_get_from_avail_list();
187         if (!lsock->iom) {
188                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_ENVIRONMENT,24, "can not get lsock_iomux");
189                 return NULL;
190         }
191
192         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
193                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,22, "creating lsock %p", lsock);
194         }
195         lsock->proto = proto;
196         lsock->iom->fd = socket(PF_INET, stype, proto);  //create a socket to get connection request from the client
197         if (lsock->iom->fd < 0) {
198                 if (proto == IPPROTO_TCP) {
199                         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SYSTEM_SOCKET,22,
200                                  "socket: Protocol is IPPROTO_TCP,SockType is SOCK_STREAM (%s)", strerror(errno));
201                 }
202                 else {
203                         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SYSTEM_SOCKET,26,
204                                  "socket: Protocol is IPPROTO_UDP,SockType is SOCK_DGRAM (%s)", strerror(errno));
205                 }
206  
207                 if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
208                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,7,
209                                                 "in function l7vs_lsock_get: free memory"
210                                                 " : size=%zu ,pointer=%p",
211                                                 sizeof(*lsock),lsock);
212                 }
213                 free(lsock);
214                 return NULL;
215         }
216
217         setsockopt(lsock->iom->fd, SOL_SOCKET, SO_REUSEADDR, (char*) &on, sizeof(int));
218         ret = bind(lsock->iom->fd, (struct sockaddr *)sin, sizeof(*sin)); //binding the socket for incoming client request
219         if (ret < 0) {
220                 char addr_str[DEBUG_STR_LEN]={0};
221
222                 l7vs_lsock_sockaddr_in_c_str(addr_str, (struct sockaddr_in *)sin);
223                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SYSTEM_SOCKET,23, "Could not bind socket: %s (%s)",
224                                           addr_str,strerror(errno));
225                 close(lsock->iom->fd);
226                 if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
227                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,8,
228                                                 "in function l7vs_lsock_get: free memory"
229                                                 " : size=%zu ,pointer=%p",
230                                                 sizeof(*lsock),lsock);
231                 }
232                 free(lsock);
233                 return NULL;
234         }
235         lsock->addr = *sin;
236
237         ret = listen(lsock->iom->fd, backlog); //listening for client requests
238         if (ret < 0) {
239                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SYSTEM_SOCKET,24, "Could not listen: %s (file descriptor :%d , backlog: %d)",
240                                           strerror(errno),lsock->iom->fd, backlog);
241                 close(lsock->iom->fd);
242                 if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
243                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,9,
244                                                 "in function l7vs_lsock_get: free memory"
245                                                 " : size=%zu ,pointer=%p",
246                                                 sizeof(*lsock),lsock);
247                 }
248                 free(lsock);
249                 return NULL;
250         }
251
252         lsock->refcnt = 1;
253         lsock->fast_schedule = 1;
254
255         lsock->iom->callback = l7vs_lsock_callback;
256         lsock->iom->data = lsock;
257         lsock->iom->status = iomux_lsock_connect_waiting;
258         l7vs_lsock_table_add(lsock);  //Add socket in the list. It may be used for maintaining session (Am not sure)
259 //        l7vs_iomux_add(&lsock->iom, L7VS_IOMUX_READ);
260
261         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
262                 char lsock_str[DEBUG_STR_LEN] = {0};
263                 l7vs_lsock_c_str(lsock_str, lsock);
264                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,23,
265                                       "creat: lsock=%s",
266                                        lsock_str);
267         }
268         l7vs_iomux_add( lsock->iom, iom_read );
269         return lsock;
270 }
271
272 /*!
273  * lisning socket remove list and iomuxlist.
274  * @param[in]   lsock   removing lisning socket
275  * @return      void
276  */
277
278 void
279 l7vs_lsock_put(struct l7vs_lsock *lsock)
280 {
281         if(lsock == NULL)
282         {
283                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SYSTEM_SOCKET,25, "error / lsock is null");
284                 return;
285         }
286
287         lsock->iom->status = iomux_lsock_released;
288
289         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
290                 char lsock_str[DEBUG_STR_LEN] = {0};
291                 l7vs_lsock_c_str(lsock_str, lsock);
292                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,24,
293                                      "lsock  removing : lsock=%s",
294                                       lsock_str);
295         }
296         if (--lsock->refcnt > 0)
297         {
298                 lsock->iom->status = iomux_lsock_connect_waiting;
299                 if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
300                         char lsock_str[DEBUG_STR_LEN] = {0};
301                         l7vs_lsock_c_str(lsock_str, lsock);
302                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,25,
303                                       "not removing : lsock=%s",
304                                        lsock_str);
305                 }
306                 return;
307         }
308
309         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
310                 char lsock_str[DEBUG_STR_LEN] = {0};
311                 l7vs_lsock_c_str(lsock_str, lsock);
312                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,26,
313                                      "removing : lsock=%s",
314                                       lsock_str);
315         }
316
317         lsock->iom->status = iomux_lsock_destroyed;
318
319         l7vs_iomux_remove(lsock->iom);
320         l7vs_lsock_table_remove(lsock);
321
322         if(lsock->iom->fd > 0)
323         {
324                 close(lsock->iom->fd);
325         }
326         l7vs_iomux_put_to_avail_list(lsock->iom);
327
328         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY) == LOG_LV_DEBUG){
329                 char lsock_str[DEBUG_STR_LEN] = {0};
330                 l7vs_lsock_c_str(lsock_str, lsock);
331                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_MEMORY,10,
332                                      "in function l7vs_lsock_put  : free lsock=%p",
333                                       lsock);
334         }
335         free(lsock);
336 }
337
338 /*!
339  * lsock_list append new lsock ponter
340  * @param[in]   lsock   to insert table lsock
341  * @return      void
342  */
343 static void
344 l7vs_lsock_table_add(struct l7vs_lsock *lsock)
345 {
346         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
347                 char lsock_str[DEBUG_STR_LEN] = {0};
348                 l7vs_lsock_c_str(lsock_str, lsock);
349                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,27,
350                                      "in_function l7vs_lsock_table_add : add table lsock=%s",
351                                       lsock_str);
352         }
353         l7vs_lsock_list = g_list_append(l7vs_lsock_list, (gpointer)lsock);
354         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
355                 char lsock_str[DEBUG_STR_LEN] = {0};
356                 l7vs_lsock_c_str(lsock_str, lsock);
357                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,28,
358                                      "out_function l7vs_lsock_table_add : add table lsock=%s",
359                                       lsock_str);
360         }
361 }
362
363 /*!
364  * lsock_list remove lsock (don't free element)
365  * @param[in]   to remove lsock
366  * @return      void
367  */
368 static void
369 l7vs_lsock_table_remove(struct l7vs_lsock *lsock)
370 {
371         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
372                 char lsock_str[DEBUG_STR_LEN] = {0};
373                 l7vs_lsock_c_str(lsock_str, lsock);
374                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,29,
375                                      "in_function l7vs_lsock_table_remove : remove table lsock=%s",
376                                       lsock_str);
377         }
378         l7vs_lsock_list = g_list_remove(l7vs_lsock_list, (gpointer)lsock);
379         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
380                 char lsock_str[DEBUG_STR_LEN] = {0};
381                 l7vs_lsock_c_str(lsock_str, lsock);
382                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,30,
383                                      "out_function l7vs_lsock_table_remove : remove table lsock=%s",
384                                       lsock_str);
385         }
386 }
387
388
389 /*!
390  * look up table for lsock.
391  * @param[in]   *sin    socketaddr_in struct pointer (ex. to change then IPv6 target )
392  * @param[in]   *proto  port no
393  * @return      *l7vs_lsock
394  */
395 struct l7vs_lsock *
396 l7vs_lsock_table_lookup(struct sockaddr_in *sin, uint8_t proto)
397 {
398         struct l7vs_lsock tmpl;
399         GList *l;
400
401         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
402                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,31,
403                     "in_fuction:  struct l7vs_lsock * l7vs_lsock_table_lookup(struct sockaddr_in *sin, uint8_t proto)"
404                                 "*sin =%p :proto = %d ",
405                                 sin,proto);
406         }
407
408         if(sin == NULL)
409         {
410                 return NULL;
411         }
412
413         tmpl.addr = *sin;
414         tmpl.proto = proto;
415
416         l = g_list_find_custom(l7vs_lsock_list, (gpointer)&tmpl,
417                                l7vs_lsock_addr_cmp);
418         if (l == NULL)
419                 return NULL;
420         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
421                 char lsock_str[DEBUG_STR_LEN] = {0};
422                 l7vs_lsock_c_str(lsock_str, (struct l7vs_lsock *)l->data);
423                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,32,
424                                      "return : lsock=%s",
425                                       lsock_str);
426         }
427         return (struct l7vs_lsock *)l->data;  //for checking up and finding the socket in the list for a particular client socket(not sure)
428 }
429
430 /*!
431  * using foreach function from Compare
432  * @param       a l7vs_lsock pointer
433  * @param       b l7vs_lsock pointer
434  * @return      compare pattern 
435  */
436 static gint
437 l7vs_lsock_addr_cmp(gconstpointer a, gconstpointer b)
438 {
439         struct l7vs_lsock *la = (struct l7vs_lsock *)a;
440         struct l7vs_lsock *lb = (struct l7vs_lsock *)b;
441
442
443         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
444                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,33,
445                     "in_fuction:  gint l7vs_lsock_addr_cmp(gconstpointer a, gconstpointer b)"
446                                 "a =%p :b = %p ",
447                                 a,b);
448         }
449
450         if (la->addr.sin_addr.s_addr != lb->addr.sin_addr.s_addr)
451                 return la->addr.sin_addr.s_addr - lb->addr.sin_addr.s_addr;
452         if (la->addr.sin_port != lb->addr.sin_port)
453                 return la->addr.sin_port - lb->addr.sin_port;
454         if (la->proto != lb->proto)
455                 return la->proto - lb->proto;
456
457         if(logger_get_log_level(LOG_CAT_L7VSD_SYSTEM_SOCKET) == LOG_LV_DEBUG){
458                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SYSTEM_SOCKET,34,
459                     "out_fuction:  gint l7vs_lsock_addr_cmp(gconstpointer a, gconstpointer b)"
460                                 "return = 0");
461         }
462         return 0;
463 }
464
465 /*!
466  * select VertualService or SorryServer
467  * @param       lsock l7vs_lsock pointer
468  * @param       conn  l7vs_conn pointer
469  * @param       buf   char pointer
470  * @param       len   size_t
471  * @param       srv_ret  l7vs_service pointer pointer
472  * @param       dest_ret l7vs_dest pointer pointer
473  * @param       tcps_ret int pointer
474  * @return      int   ok:1 error:-1
475  */
476 int
477 l7vs_lsock_select_service(struct l7vs_lsock *lsock, 
478                           struct l7vs_conn *conn,
479                           char *buf,
480                           size_t len,
481                           struct l7vs_service **srv_ret,
482                           struct l7vs_dest **dest_ret,
483                           int *tcps_ret)
484 {
485         GList *l;
486         struct l7vs_service *srv;
487         struct l7vs_dest *dest;
488         int ret, val;
489         int tcps;
490         struct l7vs_service *srv_tmp = NULL;    //! temporary for srv
491         struct l7vs_dest *dest_tmp = NULL;      //! temporary for dest
492         int tcps_tmp = 1;                       //! temporary for tcps
493         size_t len_tmp = 0;                     //! temporary for len
494         int sorry_save = 0;                     //! sorry dest save flag
495         struct l7vs_service *srv_tmp2 = NULL;   //! temporary for srv when match_cldata NG
496         struct l7vs_dest *dest_tmp2 = NULL;     //! temporary for dest when match_cldata NG
497         int tcps_tmp2 = 1;                      //! temporary for tcps when match_cldata NG
498         size_t len_tmp2 = 0;                    //! temporary for len when match_cldata NG
499         int sorry_save2 = 0;                    //! sorry dest save flag when match_cldata NG
500
501         if(logger_get_log_level(LOG_CAT_L7VSD_REAL_SERVER) == LOG_LV_DEBUG){
502                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_REAL_SERVER,13,
503                     "in_fuction:  int l7vs_lsock_select_service(struct l7vs_lsock *lsock,"
504                         "struct l7vs_conn *conn,"
505                         "char *buf,"
506                         "size_t len,"
507                         "struct l7vs_service **srv_ret,"
508                         "struct l7vs_dest **dest_ret,"
509                         "int *tcps_ret)"
510                         "lsock :%p, conn :%p buf : %p,len : %zu,",
511                         lsock,conn,buf,len);
512                         
513         }
514         val = -1;
515         l = lsock->srv_list;
516         while (l != NULL) {
517                 srv = (struct l7vs_service *)l->data;
518                 dest = NULL;
519                 tcps = 1;
520                 ret = srv->pm->match_cldata(srv, conn, buf, &len, &dest, &tcps);
521                 if (ret == 0) {
522                         // check sorry status if ret == 0
523                         // sorry_check argument 1 means check connection count
524                         if (l7vs_sched_sorry_check(srv, 1)) {
525                                 if (!sorry_save) {
526                                         // save sorry dest to xxx_tmp only first time
527                                         srv_tmp = srv;
528                                         dest_tmp = dest;
529                                         tcps_tmp = tcps;
530                                         len_tmp = len;
531                                         sorry_save = 1;
532                                 }
533                         } else {
534                                 // check cldata length if sorry_check != 1 (not sorry status)
535                                 if (len > conn->cldata_len + L7VS_PROTOMOD_MAX_ADD_BUFSIZE) {
536                                         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SORRY_SERVER,1, "bufsize too long modified by protomod ");
537                                 } else {
538                                         // service and destination is decided
539                                         *srv_ret = srv;
540                                         *dest_ret = dest;
541                                         *tcps_ret = tcps;
542                                         conn->cldata_len = len;
543                                         sorry_save = 0;
544                                         sorry_save2 = 0;
545                                         val = 1;
546                                         break;
547                                 }
548                         }
549                 }
550                 // when match_cldata NG
551                 if (!sorry_save2) {
552                         // save sorry dest to xxx_tmp2 only first time
553                         srv_tmp2 = srv;
554                         dest_tmp2 = dest;
555                         tcps_tmp2 = tcps;
556                         len_tmp2 = len;
557                         sorry_save2 = 1;
558                 }
559                 // get next srv from srv_list
560                 l = g_list_next(l);
561         }
562
563         if (sorry_save) {
564                 // saved sorry dest is exist
565                 // set sorry-server destination
566                 //*dest_ret = (struct l7vs_dest *)l7vs_sched_sorry_dest(srv_tmp, NULL, 1);
567                 *dest_ret = (struct l7vs_dest *)l7vs_sched_sorry_dest(srv_tmp, NULL, 0);
568                 if (!*dest_ret) {
569                         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SORRY_SERVER,2, "sorry-server dest is NULL");
570                         if(logger_get_log_level(LOG_CAT_L7VSD_REAL_SERVER) == LOG_LV_DEBUG){
571                                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_REAL_SERVER,14,
572                                 "in_fuction:  int l7vs_lsock_select_service return -1");
573                         }
574                         return -1;
575                 }
576                 *srv_ret = srv_tmp;
577                 *tcps_ret = tcps_tmp;
578                 conn->cldata_len = len_tmp;
579                 conn->sorry_conn_flag = 1;
580                 val = 1;
581         } else if (sorry_save2) {
582                 // saved sorry dest2 is exist
583                 // set sorry-server destination
584                 //*dest_ret = (struct l7vs_dest *)l7vs_sched_sorry_dest(srv_tmp2, NULL, 1);
585                 *dest_ret = (struct l7vs_dest *)l7vs_sched_sorry_dest(srv_tmp2, NULL, 0);
586                 if (!*dest_ret) {
587                         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SORRY_SERVER,3, "sorry-server dest is NULL");
588                         if(logger_get_log_level(LOG_CAT_L7VSD_REAL_SERVER) == LOG_LV_DEBUG){
589                                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_REAL_SERVER,15,
590                                 "in_fuction:  int l7vs_lsock_select_service return -1");
591                         }
592                         return -1;
593                 }
594                 *srv_ret = srv_tmp2;
595                 *tcps_ret = tcps_tmp2;
596                 conn->cldata_len = len_tmp2;
597                 conn->sorry_conn_flag = 1;
598                 val = 1;
599         }
600         // return val=1 service and destination is decided (to real-server or sorry-server)
601         // return val=-1 service and destination not decided (match_cldata result all NG)
602         if(logger_get_log_level(LOG_CAT_L7VSD_REAL_SERVER) == LOG_LV_DEBUG){
603                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_REAL_SERVER,16,
604                 "out_fuction:  int l7vs_lsock_select_service return %d",val);
605         }
606         return val;
607 }
608
609 /*!
610  * table add service list
611  *  append list memory.
612  * @param[in]   void
613  * @return      void
614  */
615 void
616 l7vs_lsock_add_service(struct l7vs_lsock *lsock,
617                        struct l7vs_service *srv)
618 {
619         if(logger_get_log_level(LOG_CAT_L7VSD_VIRTUAL_SERVICE) == LOG_LV_DEBUG){
620                 char lsock_str[DEBUG_STR_LEN] = {0};
621                 l7vs_lsock_c_str(lsock_str, lsock);
622
623                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,94,
624                 "in_fuction:  void l7vs_lsock_add_service(struct l7vs_lsock *lsock,struct l7vs_service *srv)"
625                 "lsock: %s,srv : %p",
626                 lsock_str,srv);
627         }
628         lsock->srv_list = g_list_append(lsock->srv_list, srv);
629         if (lsock->fast_schedule) {
630                 lsock->fast_schedule = srv->pm->fast_schedule;
631         }
632         if(logger_get_log_level(LOG_CAT_L7VSD_VIRTUAL_SERVICE) == LOG_LV_DEBUG){
633                 char lsock_str[DEBUG_STR_LEN] = {0};
634                 l7vs_lsock_c_str(lsock_str, lsock);
635
636                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,95,
637                 "out_fuction:  void l7vs_lsock_add_service(struct l7vs_lsock *lsock,struct l7vs_service *srv)"
638                 "lsock: %s,srv : %p",
639                 lsock_str,srv);
640         }
641 }
642
643 /*!
644  * table remove from service list
645  *  remove list memory.
646  * @param[in]   void
647  * @return      void
648  */
649 void
650 l7vs_lsock_remove_service(struct l7vs_lsock *lsock,
651                           struct l7vs_service *srv)
652 {
653         GList* slist = NULL;
654         if(logger_get_log_level(LOG_CAT_L7VSD_VIRTUAL_SERVICE) == LOG_LV_DEBUG){
655                 char lsock_str[DEBUG_STR_LEN] = {0};
656                 l7vs_lsock_c_str(lsock_str, lsock);
657
658                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,96,
659                 "in_fuction:  void l7vs_lsock_remove_service (struct l7vs_lsock *lsock,struct l7vs_service *srv)"
660                 "lsock: %s,srv : %p",
661                 lsock_str,srv);
662         }
663         lsock->srv_list = g_list_remove(lsock->srv_list, srv);
664         lsock->fast_schedule = 1;
665         for (slist = g_list_first(lsock->srv_list); slist != NULL; slist = slist->next) {
666                 struct l7vs_service* s = (struct l7vs_service*) slist->data;
667                 if (s != NULL && s->pm != NULL && s->pm->fast_schedule == 0) {
668                         lsock->fast_schedule = 0;
669                         break;
670                 }
671         }
672         if(logger_get_log_level(LOG_CAT_L7VSD_VIRTUAL_SERVICE) == LOG_LV_DEBUG){
673                 char lsock_str[DEBUG_STR_LEN] = {0};
674                 l7vs_lsock_c_str(lsock_str, lsock);
675
676                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,97,
677                 "out_fuction:  void l7vs_lsock_remove_service (struct l7vs_lsock *lsock,struct l7vs_service *srv)"
678                 "lsock: %s,srv : %p",
679                 lsock_str,srv);
680         }
681 }
682
683 /*!
684  * socket acception function.
685  * @param[in]   socket option
686  * @return      success = 0 / false = -1
687  */
688 static int
689 l7vs_lsock_accept(struct l7vs_lsock *lsock)
690 {
691         if(lsock == NULL)
692         {
693                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,20, "error / lsock is null");
694                 if(logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG){
695                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,50,
696                          "out_fuction:  int l7vs_lsock_accept return -1");
697                 }
698                 return -1;
699         }
700         if(logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG){
701                 char lsock_str[DEBUG_STR_LEN] = {0};
702                 l7vs_lsock_c_str(lsock_str, lsock);
703                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,51,
704                 "in_fuction:  int l7vs_lsock_accept (struct l7vs_lsock *lsock)"
705                 "lsock: %s",
706                 lsock_str);
707         }
708         if (iomux_lsock_accepted != lsock->iom->status)
709         {
710                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,21, "error / invalid status(%d)", lsock->iom->status);
711                 if(logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG){
712                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,52,
713                          "out_fuction:  int l7vs_lsock_accept return -1");
714                 }
715                 return -1;
716         }
717
718         if (!l7vs_conn_create(lsock->iom->fd, lsock))
719         {
720                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,22, "error / conn create failed");
721                 lsock->iom->status = iomux_lsock_conn_create_error;
722                 if(logger_get_log_level(LOG_CAT_L7VSD_ENVIRONMENT) == LOG_LV_DEBUG){
723                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_ENVIRONMENT,8,
724                          "out_fuction:  int l7vs_lsock_accept return -1");
725                 }
726                 return -1;
727         }
728
729         lsock->iom->status = iomux_lsock_conn_created;
730         if(logger_get_log_level(LOG_CAT_L7VSD_ENVIRONMENT) == LOG_LV_DEBUG){
731                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_ENVIRONMENT,9,
732                  "out_fuction:  int l7vs_lsock_accept return 0");
733         }
734         return 0;
735 }
736
737 /*!
738  * ListeningSocket call back function.
739  * @param[in]   socket option
740  * @return      success = 0 / false = -1
741  */
742 static int
743 l7vs_lsock_callback(struct l7vs_iomux *iom )
744 {
745
746         int ret;
747
748         if(iom == NULL)
749         {
750                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,23, "error / iom is null");
751                 if(logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG){
752                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,53,
753                         "out_fuction:  int l7vs_lsock_callback return -1");
754                 }
755                 return -1;
756         }
757
758         if(logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG){
759                 char iomux_str[DEBUG_STR_LEN] = {0};
760                 l7vs_iomux_c_str(iomux_str,iom);
761                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,54,
762                 "in_fuction:  int l7vs_lsock_callback (struct l7vs_iomux *iom)"
763                 "iom: %s",
764                 iomux_str);
765         }
766
767         if (iomux_lsock_connect_waiting != iom->status)
768         {
769                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,24, "error / invalid status(%d)", iom->status);
770                 if(logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG){
771                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,55,
772                         "out_fuction:  int l7vs_lsock_callback return -1");
773                 }
774                 return -1;
775         }
776
777         iom->status = iomux_lsock_accepted;
778         ret = l7vs_lsock_accept((struct l7vs_lsock *)iom->data); //for accepting data from clients
779         if (-1 == ret)
780         {
781                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,25, "error / lsock accept failed");
782                 iom->status = iomux_lsock_connect_waiting;
783                 l7vs_iomux_mod( iom, iom_read );
784                 if(logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG){
785                         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,56,
786                         "out_fuction:  int l7vs_lsock_callback return -1");
787                 }
788                 return -1;
789         }
790
791         iom->status = iomux_lsock_connect_waiting;
792         l7vs_iomux_mod( iom, iom_read );
793         if(logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG){
794                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,57,
795                 "out_fuction:  int l7vs_lsock_callback return 0");
796         }
797
798         return 0; 
799 }
800