OSDN Git Service

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