OSDN Git Service

Set old destination for changing connection from sorry server to real server.
[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             // Check the connection count(--upper, maxconn)
496             if (l7vs_sched_sorry_check(srv, 1)) {
497                 if (!sorry_save) {
498                     // save sorry dest to xxx_tmp only first time
499                     srv_tmp = srv;
500                     dest_tmp = dest;
501                     len_tmp = len;
502                     sorry_save = 1;
503                 }
504             } else {
505                 // check cldata length if sorry_check != 1 (not sorry status)
506                 if (len > conn->cldata_len + L7VS_PROTOMOD_MAX_ADD_BUFSIZE) {
507                     LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SORRY_SERVER,1, "bufsize too long modified by protomod ");
508                 } else {
509                     // service and destination is decided
510                     *srv_ret = srv;
511                     *dest_ret = dest;
512                     conn->cldata_len = len;
513                     sorry_save = 0;
514                     sorry_save2 = 0;
515                     val = 1;
516                     break;
517                 }
518             }
519         }
520         // when select_dest NG
521         // No suitable realservers exist
522         if (!sorry_save2) {
523             // save sorry dest to xxx_tmp2 only first time
524             srv_tmp2 = srv;
525             dest_tmp2 = dest;
526             len_tmp2 = len;
527             sorry_save2 = 1;
528         }
529         // get next srv from srv_list
530         l = g_list_next(l);
531     }
532
533     // Over maximum connections
534     if (sorry_save) {
535         // saved sorry dest is exist
536         // set sorry-server destination
537         *dest_ret = (struct l7vs_dest *)l7vs_sched_sorry_dest(srv_tmp, NULL, 0);
538         if (!*dest_ret) {
539             LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SORRY_SERVER,2, "sorry-server dest is NULL");
540             if (logger_get_log_level(LOG_CAT_L7VSD_REAL_SERVER) == LOG_LV_DEBUG) {
541                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_REAL_SERVER,14,
542                     "in_fuction:  int l7vs_lsock_select_service return -1");
543             }
544             return -1;
545         }
546         *srv_ret = srv_tmp;
547         conn->old_dest = dest_tmp;
548         conn->cldata_len = len_tmp;
549         conn->sorry_conn_flag = 1;
550         val = 1;
551
552     // No suitable realservers exist
553     } else if (sorry_save2) {
554         // saved sorry dest2 is exist
555         // set sorry-server destination
556         *dest_ret = (struct l7vs_dest *)l7vs_sched_sorry_dest(srv_tmp2, NULL, 0);
557         if (!*dest_ret) {
558             LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SORRY_SERVER,3, "sorry-server dest is NULL");
559             if (logger_get_log_level(LOG_CAT_L7VSD_REAL_SERVER) == LOG_LV_DEBUG) {
560                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_REAL_SERVER,15,
561                     "in_fuction:  int l7vs_lsock_select_service return -1");
562             }
563             return -1;
564         }
565         *srv_ret = srv_tmp2;
566         conn->old_dest = dest_tmp2;
567         conn->cldata_len = len_tmp2;
568         conn->sorry_conn_flag = 1;
569         val = 1;
570     }
571     // return val=1 service and destination is decided (to real-server or sorry-server)
572     // return val=-1 service and destination not decided (select_dest result all NG)
573     if (logger_get_log_level(LOG_CAT_L7VSD_REAL_SERVER) == LOG_LV_DEBUG) {
574         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_REAL_SERVER,16,
575             "out_fuction:  int l7vs_lsock_select_service return %d",val);
576     }
577     return val;
578 }
579
580 /*!
581  * table add service list
582  *  append list memory.
583  * @param[in]   void
584  * @return      void
585  */
586 void
587 l7vs_lsock_add_service(struct l7vs_lsock *lsock,
588                        struct l7vs_service *srv)
589 {
590     if (logger_get_log_level(LOG_CAT_L7VSD_VIRTUAL_SERVICE) == LOG_LV_DEBUG) {
591         char lsock_str[DEBUG_STR_LEN] = {0};
592         l7vs_lsock_c_str(lsock_str, lsock);
593
594         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,94,
595             "in_fuction:  void l7vs_lsock_add_service(struct l7vs_lsock *lsock,struct l7vs_service *srv)"
596             "lsock: %s,srv : %p",
597             lsock_str,srv);
598     }
599     lsock->srv_list = g_list_append(lsock->srv_list, srv);
600     if (lsock->fast_schedule) {
601         lsock->fast_schedule = srv->pm->fast_schedule;
602     }
603     if (logger_get_log_level(LOG_CAT_L7VSD_VIRTUAL_SERVICE) == LOG_LV_DEBUG) {
604         char lsock_str[DEBUG_STR_LEN] = {0};
605         l7vs_lsock_c_str(lsock_str, lsock);
606
607         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,95,
608             "out_fuction:  void l7vs_lsock_add_service(struct l7vs_lsock *lsock,struct l7vs_service *srv)"
609             "lsock: %s,srv : %p", lsock_str,srv);
610     }
611 }
612
613 /*!
614  * table remove from service list
615  *  remove list memory.
616  * @param[in]   void
617  * @return      void
618  */
619 void
620 l7vs_lsock_remove_service(struct l7vs_lsock *lsock,
621                           struct l7vs_service *srv)
622 {
623     GList* slist = NULL;
624     if (logger_get_log_level(LOG_CAT_L7VSD_VIRTUAL_SERVICE) == LOG_LV_DEBUG) {
625         char lsock_str[DEBUG_STR_LEN] = {0};
626         l7vs_lsock_c_str(lsock_str, lsock);
627
628         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,96,
629             "in_fuction:  void l7vs_lsock_remove_service (struct l7vs_lsock *lsock,struct l7vs_service *srv)"
630             "lsock: %s,srv : %p",
631             lsock_str,srv);
632     }
633     lsock->srv_list = g_list_remove(lsock->srv_list, srv);
634     lsock->fast_schedule = 1;
635     for (slist = g_list_first(lsock->srv_list); slist != NULL; slist = slist->next) {
636         struct l7vs_service* s = (struct l7vs_service*) slist->data;
637         if (s != NULL && s->pm != NULL && s->pm->fast_schedule == 0) {
638             lsock->fast_schedule = 0;
639             break;
640         }
641     }
642     if (logger_get_log_level(LOG_CAT_L7VSD_VIRTUAL_SERVICE) == LOG_LV_DEBUG) {
643         char lsock_str[DEBUG_STR_LEN] = {0};
644         l7vs_lsock_c_str(lsock_str, lsock);
645
646         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,97,
647             "out_fuction:  void l7vs_lsock_remove_service (struct l7vs_lsock *lsock,struct l7vs_service *srv)"
648             "lsock: %s,srv : %p",
649             lsock_str,srv);
650     }
651 }
652
653 /*!
654  * socket acception function.
655  * @param[in]   lsock   socket option
656  * @return      success = 0 / false = -1
657  */
658 static int
659 l7vs_lsock_accept(struct l7vs_lsock *lsock)
660 {
661     if (lsock == NULL) {
662         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,20, "error / lsock is null");
663         if (logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG) {
664             LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,50,
665                 "out_fuction:  int l7vs_lsock_accept return -1");
666         }
667         return -1;
668     }
669     if (logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG) {
670         char lsock_str[DEBUG_STR_LEN] = {0};
671         l7vs_lsock_c_str(lsock_str, lsock);
672         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,51,
673             "in_fuction:  int l7vs_lsock_accept (struct l7vs_lsock *lsock)"
674             "lsock: %s", lsock_str);
675     }
676     if (iomux_lsock_accepted != lsock->iom->status) {
677         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,21, "error / invalid status(%d)", lsock->iom->status);
678         if (logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG) {
679             LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,52,
680                 "out_fuction:  int l7vs_lsock_accept return -1");
681         }
682         return -1;
683     }
684
685     if (!l7vs_conn_create(lsock->iom->fd, lsock)) {
686         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,22, "error / conn create failed");
687         lsock->iom->status = iomux_lsock_conn_create_error;
688         if (logger_get_log_level(LOG_CAT_L7VSD_ENVIRONMENT) == LOG_LV_DEBUG) {
689             LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_ENVIRONMENT,8,
690                 "out_fuction:  int l7vs_lsock_accept return -1");
691         }
692         return -1;
693     }
694
695     lsock->iom->status = iomux_lsock_conn_created;
696     if (logger_get_log_level(LOG_CAT_L7VSD_ENVIRONMENT) == LOG_LV_DEBUG) {
697         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_ENVIRONMENT,9,
698             "out_fuction:  int l7vs_lsock_accept return 0");
699     }
700     return 0;
701 }
702
703 /*!
704  * ListeningSocket call back function.
705  * @param[in]   iom socket option
706  * @return      success = 0 / false = -1
707  */
708 static int
709 l7vs_lsock_callback(struct l7vs_iomux *iom )
710 {
711     int ret;
712
713     if (iom == NULL) {
714         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,23, "error / iom is null");
715         if (logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG) {
716             LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,53,
717                 "out_fuction:  int l7vs_lsock_callback return -1");
718         }
719         return -1;
720     }
721
722     if (logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG) {
723         char iomux_str[DEBUG_STR_LEN] = {0};
724         l7vs_iomux_c_str(iomux_str,iom);
725         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,54,
726             "in_fuction:  int l7vs_lsock_callback (struct l7vs_iomux *iom)"
727             "iom: %s", iomux_str);
728     }
729
730     if (iomux_lsock_connect_waiting != iom->status) {
731         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,24, "error / invalid status(%d)", iom->status);
732         if (logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG) {
733             LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,55,
734                 "out_fuction:  int l7vs_lsock_callback return -1");
735         }
736         return -1;
737     }
738
739     iom->status = iomux_lsock_accepted;
740     ret = l7vs_lsock_accept((struct l7vs_lsock *)iom->data); //for accepting data from clients
741     if (-1 == ret) {
742         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_EVENT,25, "error / lsock accept failed");
743         iom->status = iomux_lsock_connect_waiting;
744         l7vs_iomux_mod( iom, iom_read );
745         if (logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG) {
746             LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,56,
747                 "out_fuction:  int l7vs_lsock_callback return -1");
748         }
749         return -1;
750     }
751
752     iom->status = iomux_lsock_connect_waiting;
753     l7vs_iomux_mod( iom, iom_read );
754     if (logger_get_log_level(LOG_CAT_L7VSD_EVENT) == LOG_LV_DEBUG) {
755         LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_EVENT,57,
756             "out_fuction:  int l7vs_lsock_callback return 0");
757     }
758
759     return 0; 
760 }