/[svn]/branches/newio/src/listener.c
ViewVC logotype

Diff of /branches/newio/src/listener.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2395 by michael, Sat Jul 13 22:13:28 2013 UTC revision 2396 by michael, Mon Jul 15 19:51:03 2013 UTC
# Line 24  Line 24 
24    
25  #include "stdinc.h"  #include "stdinc.h"
26  #include "list.h"  #include "list.h"
27    #include "ioengine.h"
28  #include "listener.h"  #include "listener.h"
29  #include "client.h"  #include "client.h"
30  #include "irc_string.h"  #include "irc_string.h"
# Line 35  Line 36 
36  #include "send.h"  #include "send.h"
37  #include "memory.h"  #include "memory.h"
38    
 static PF accept_connection;  
39    
40  static dlink_list ListenerPollList = { NULL, NULL, 0 };  static dlink_list listener_list;
41  static void close_listener(struct Listener *listener);  
42    
43  static struct Listener *  static struct Listener *
44  make_listener(int port, struct irc_ssaddr *addr)  make_listener(int port, struct irc_ssaddr *addr)
45  {  {
46    struct Listener *listener = MyMalloc(sizeof(struct Listener));    struct Listener *listener = MyMalloc(sizeof(struct Listener));
47    
48      listener->fd   = -1;
49    listener->port = port;    listener->port = port;
50    memcpy(&listener->addr, addr, sizeof(struct irc_ssaddr));    memcpy(&listener->addr, addr, sizeof(struct irc_ssaddr));
51    
52    return listener;    return listener;
53  }  }
54    
55  void  /** Deallocate a Listener structure.
56  free_listener(struct Listener *listener)   * @param[in] listener Listener to be freed.
57     */
58    static void
59    listener_free(struct listener *listener)
60  {  {
61    assert(listener != NULL);    assert(listener);
62      assert(listener->active    == 0);
63      assert(listener->ref_count == 0);
64    
   dlinkDelete(&listener->node, &ListenerPollList);  
65    MyFree(listener);    MyFree(listener);
66  }  }
67    
# Line 87  show_ports(struct Client *source_p) Line 92  show_ports(struct Client *source_p)
92    char *p = NULL;    char *p = NULL;
93    dlink_node *ptr;    dlink_node *ptr;
94    
95    DLINK_FOREACH(ptr, ListenerPollList.head)    DLINK_FOREACH(ptr, listener_list.head)
96    {    {
97      const struct Listener *listener = ptr->data;      const struct Listener *listener = ptr->data;
98      p = buf;      p = buf;
99    
100      if (listener->flags & LISTENER_HIDDEN) {      if (listener->flags & LISTENER_HIDDEN)
101        {
102        if (!HasUMode(source_p, UMODE_ADMIN))        if (!HasUMode(source_p, UMODE_ADMIN))
103          continue;          continue;
104        *p++ = 'H';        *p++ = 'H';
# Line 120  show_ports(struct Client *source_p) Line 126  show_ports(struct Client *source_p)
126   * use HYBRID_SOMAXCONN   * use HYBRID_SOMAXCONN
127   */   */
128  #ifdef SOMAXCONN  #ifdef SOMAXCONN
 #undef HYBRID_SOMAXCONN  
129  #define HYBRID_SOMAXCONN SOMAXCONN  #define HYBRID_SOMAXCONN SOMAXCONN
130    #else
131    /** Maximum length of socket connection backlog. */
132    #define HYBRID_SOMAXCONN 64
133  #endif  #endif
134    
135    /** Open listening socket for \a listener.
136     * @param[in,out] listener Listener to make a socket for.
137     * @return Non-zero on success, zero on failure.
138     */
139  static int  static int
140  inetport(struct Listener *listener)  inetport(struct Listener *listener)
141  {  {
# Line 185  inetport(struct Listener *listener) Line 197  inetport(struct Listener *listener)
197  }  }
198    
199  static struct Listener *  static struct Listener *
200  find_listener(int port, struct irc_ssaddr *addr)  find_listener(int port, const struct irc_ssaddr *addr)
201  {  {
202    dlink_node *ptr;    dlink_node *ptr = NULL;
   struct Listener *listener    = NULL;  
   struct Listener *last_closed = NULL;  
203    
204    DLINK_FOREACH(ptr, ListenerPollList.head)    DLINK_FOREACH(ptr, ListenerPollList.head)
205    {    {
206      listener = ptr->data;      struct Listener *listener = ptr->data;
207    
208      if ((port == listener->port) &&      if ((port == listener->port) &&
209          (!memcmp(addr, &listener->addr, sizeof(struct irc_ssaddr))))          (!memcmp(addr, &listener->addr, sizeof(struct irc_ssaddr))))
210      {        return listener;
       /* Try to return an open listener, otherwise reuse a closed one */  
       if (!listener->fd.flags.open)  
         last_closed = listener;  
       else  
         return (listener);  
     }  
211    }    }
212    
213    return (last_closed);    return NULL;
214  }  }
215    
216  /*  /*
# Line 228  add_listener(int port, const char *vhost Line 232  add_listener(int port, const char *vhost
232  #endif  #endif
233    
234    /*    /*
235     * if no or invalid port in conf line, don't bother     * If no or invalid port in conf line, don't bother
236     */     */
237    if (!(port > 0 && port <= 0xFFFF))    if (!(port > 0 && port <= 0xFFFF))
238      return;      return;
239    
240    memset(&vaddr, 0, sizeof(vaddr));    memset(&vaddr, 0, sizeof(vaddr));
   
   /* Set up the hints structure */  
241    memset(&hints, 0, sizeof(hints));    memset(&hints, 0, sizeof(hints));
242    
243    hints.ai_family = AF_UNSPEC;    hints.ai_family = AF_UNSPEC;
244    hints.ai_socktype = SOCK_STREAM;    hints.ai_socktype = SOCK_STREAM;
245    /* Get us ready for a bind() and don't bother doing dns lookup */    /* Get us ready for a bind() and don't bother doing dns lookup */
246    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
247    
248  #ifdef IPV6    snprintf(portname, sizeof(portname), "%d", port);
   if (ServerInfo.can_use_v6)  
   {  
     snprintf(portname, sizeof(portname), "%d", port);  
     getaddrinfo("::", portname, &hints, &res);  
     vaddr.ss.ss_family = AF_INET6;  
     assert(res != NULL);  
   
     memcpy((struct sockaddr*)&vaddr, res->ai_addr, res->ai_addrlen);  
     vaddr.ss_port = port;  
     vaddr.ss_len = res->ai_addrlen;  
     freeaddrinfo(res);  
   }  
   else  
 #endif  
   {  
     struct sockaddr_in *v4 = (struct sockaddr_in*) &vaddr;  
     v4->sin_addr.s_addr = INADDR_ANY;  
     vaddr.ss.ss_family = AF_INET;  
     vaddr.ss_len = sizeof(struct sockaddr_in);  
     v4->sin_port = htons(port);  
   }  
   
   snprintf(portname, PORTNAMELEN, "%d", port);  
249    
250    if (!EmptyString(vhost_ip))    if (!EmptyString(vhost_ip))
251    {    {
# Line 274  add_listener(int port, const char *vhost Line 254  add_listener(int port, const char *vhost
254    
255      assert(res != NULL);      assert(res != NULL);
256    
257      memcpy((struct sockaddr*)&vaddr, res->ai_addr, res->ai_addrlen);      memcpy((struct sockaddr *)&vaddr, res->ai_addr, res->ai_addrlen);
258      vaddr.ss_port = port;      vaddr.ss_port = port;
259      vaddr.ss_len = res->ai_addrlen;      vaddr.ss_len = res->ai_addrlen;
260      freeaddrinfo(res);      freeaddrinfo(res);
261    }    }
 #ifdef IPV6  
   else if (pass == 0 && ServerInfo.can_use_v6)  
   {  
     /* add the ipv4 listener if we havent already */  
     pass = 1;  
     add_listener(port, "0.0.0.0", flags);  
   }  
   pass = 0;  
 #endif  
262    
263    if ((listener = find_listener(port, &vaddr)))    if ((listener = listener_find(port, vaddr)))
264    {    {
265        listener->active = 1;
266      listener->flags = flags;      listener->flags = flags;
267      if (listener->fd.flags.open)      return;
       return;  
268    }    }
269    else  
   {  
270      listener = make_listener(port, &vaddr);      listener = make_listener(port, &vaddr);
271      dlinkAdd(listener, &listener->node, &ListenerPollList);      dlinkAdd(listener, &listener->node, &ListenerPollList);
272      listener->flags = flags;      listener->flags = flags;
273    }  
274    
275    if (inetport(listener))    if (inetport(listener))
276      listener->active = 1;      listener->active = 1;
# Line 308  add_listener(int port, const char *vhost Line 278  add_listener(int port, const char *vhost
278      close_listener(listener);      close_listener(listener);
279  }  }
280    
281  /*  /** Mark all listeners as closing (inactive).
282   * close_listener - close a single listener   * This is done so unused listeners are closed after a rehash.
283     */
284    void
285    listener_mark_closing(void)
286    {
287      dlink_node *ptr = NULL;
288    
289      DLINK_FOREACH(ptr, listener_list.head)
290        ((struct listener *)ptr->data)->active = 0;
291    }
292    
293    
294    /** Close a single listener.
295     * @param[in] listener Listener to close.
296   */   */
297  static void  static void
298  close_listener(struct Listener *listener)  listener_close(struct listener *listener)
299  {  {
300    assert(listener != NULL);    assert(listener);
301      assert(listener->active    == 0);
302      assert(listener->ref_count == 0);
303    
304    if (listener == NULL)    /*
305      return;     * remove from listener list
306       */
307      dlinkDelete(&listener->node, &listener_list);
308    
309      assert(listener->fd > -1);
310    
311    if (listener->fd.flags.open)    if (listener->fd > -1)
312      fd_close(&listener->fd);    {
313        close(listener->fd);
314        socket_del(&listener->socket);
315      }
316    
317    listener->active = 0;    listener_free(listener);
318    }
319    
320    if (listener->ref_count)  /** Close all inactive listeners. */
321      return;  void
322    listener_close_marked(void)
323    {
324      dlink_node *ptr = NULL, *ptr_next = NULL;
325    
326      /*
327       * close all 'extra' listening ports we have
328       */
329      DLINK_FOREACH_SAFE(ptr, ptr_next, listener_list.head)
330      {
331        struct listener *listener = ptr->data;
332    
333    free_listener(listener);      if (!listener->active && !listener->ref_count)
334          listener_close(listener);
335      }
336  }  }
337    
338  /*  /** Dereference the listener previously associated with a client.
339   * close_listeners - close and free all listeners that are not being used   * @param[in] listener Listener to dereference.
340   */   */
341  void  void
342  close_listeners(void)  listener_release(struct listener *listener)
343  {  {
344    dlink_node *ptr = NULL, *next_ptr = NULL;    assert(listener);
345      assert(listener->ref_count > 0);
346    
347    /* close all 'extra' listening ports we have */    if (--listener->ref_count == 0 && !listener->active)
348    DLINK_FOREACH_SAFE(ptr, next_ptr, ListenerPollList.head)      listener_close(listener);
     close_listener(ptr->data);  
349  }  }
350    
351    
352  #define TOOFAST_WARNING "ERROR :Trying to reconnect too fast.\r\n"  #define TOOFAST_WARNING "ERROR :Trying to reconnect too fast.\r\n"
353  #define DLINE_WARNING "ERROR :You have been D-lined.\r\n"  #define DLINE_WARNING "ERROR :You have been D-lined.\r\n"
354    
# Line 360  accept_connection(struct Event *ev) Line 366  accept_connection(struct Event *ev)
366    
367    memset(&addr, 0, sizeof(addr));    memset(&addr, 0, sizeof(addr));
368    
   
369    if (ev_type(ev) == ET_DESTROY)  /* Being destroyed */    if (ev_type(ev) == ET_DESTROY)  /* Being destroyed */
370      return;      return;
371    

Legend:
Removed from v.2395  
changed lines
  Added in v.2396

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28