root/src/noit_listener.c

Revision 1afde4ed656dbe3db947a99cd27b177f5a3f560f, 4.8 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

update logging to support faster avoidance, line numbers, filenames, etc.

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7
8 #include <unistd.h>
9 #include <errno.h>
10 #include <sys/time.h>
11 #include <sys/socket.h>
12 #include <sys/ioctl.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15
16 #include "eventer/eventer.h"
17 #include "utils/noit_log.h"
18 #include "noit_listener.h"
19 #include "noit_conf.h"
20
21 static int
22 noit_listener_acceptor(eventer_t e, int mask,
23                        void *closure, struct timeval *tv) {
24   int conn, newmask = EVENTER_READ;
25   socklen_t salen;
26   listener_closure_t listener_closure = (listener_closure_t)closure;
27   union {
28     struct sockaddr_in addr4;
29     struct sockaddr_in6 addr6;
30   } s;
31
32   if(mask & EVENTER_EXCEPTION) {
33     eventer_remove_fd(e->fd);
34     close(e->fd);
35     return 0;
36   }
37
38   conn = e->opset->accept(e->fd, (struct sockaddr *)&s, &salen, &newmask, e);
39   if(conn >= 0) {
40     socklen_t on = 1;
41     eventer_t newe;
42     if(ioctl(conn, FIONBIO, &on)) {
43       close(conn);
44       goto accept_bail;
45     }
46     newe = eventer_alloc();
47     newe->fd = conn;
48     newe->mask = EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
49     newe->callback = listener_closure->dispatch_callback;
50     newe->closure = listener_closure->dispatch_closure;
51     eventer_add(newe);
52   }
53  accept_bail:
54   return newmask | EVENTER_EXCEPTION;
55 }
56
57 int
58 noit_listener(char *host, unsigned short port, int type,
59               int backlog, eventer_func_t handler, void *closure) {
60   int rv, fd;
61   int8_t family;
62   socklen_t on;
63   long reuse;
64   listener_closure_t listener_closure;
65   eventer_t event;
66   union {
67     struct in_addr addr4;
68     struct in6_addr addr6;
69   } a;
70   union {
71     struct sockaddr_in addr4;
72     struct sockaddr_in6 addr6;
73   } s;
74   const char *event_name;
75
76   noitL(noit_debug, "noit_listener(%s, %d, %d, %d, %s, %p)\n",
77         host, port, type, backlog,
78         (event_name = eventer_name_for_callback(handler))?event_name:"??",
79         closure);
80   family = AF_INET;
81   rv = inet_pton(family, host, &a);
82   if(rv != 1) {
83     family = AF_INET6;
84     rv = inet_pton(family, host, &a);
85     if(rv != 1) {
86       if(!strcmp(host, "*")) {
87         family = AF_INET;
88         a.addr4.s_addr = INADDR_ANY;
89       } else {
90         noitL(noit_stderr, "Cannot translate '%s' to IP\n", host);
91         return -1;
92       }
93     }
94   }
95
96   fd = socket(family, type, 0);
97   if(fd < 0) return -1;
98
99   on = 1;
100   if(ioctl(fd, FIONBIO, &on)) {
101     close(fd);
102     return -1;
103   }
104
105   reuse = 1;
106   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
107                  (void*)&reuse, sizeof(reuse)) != 0) {
108
109     close(fd);
110     return -1;
111   }
112
113   memset(&s, 0, sizeof(s));
114   s.addr6.sin6_family = family;
115   s.addr6.sin6_port = htons(port);
116   memcpy(&s.addr6.sin6_addr, &a, sizeof(a));
117   if(bind(fd, (struct sockaddr *)&s,
118           (family == AF_INET) ?  sizeof(s.addr4) : sizeof(s.addr6)) < 0) {
119     noitL(noit_stderr, "bind failed: %s\b", strerror(errno));
120     close(fd);
121     return -1;
122   }
123
124   if(type == SOCK_STREAM) {
125     if(listen(fd, backlog) < 0) {
126       close(fd);
127       return -1;
128     }
129   }
130
131   listener_closure = calloc(1, sizeof(*listener_closure));
132   listener_closure->family = family;
133   listener_closure->port = htons(port);
134   listener_closure->dispatch_callback = handler;
135   listener_closure->dispatch_closure = closure;
136
137   event = eventer_alloc();
138   event->fd = fd;
139   event->mask = EVENTER_READ | EVENTER_EXCEPTION;
140   event->callback = noit_listener_acceptor;
141   event->closure = listener_closure;
142
143   eventer_add(event);
144   return 0;
145 }
146
147 void
148 noit_listener_init() {
149   int i, cnt = 0;
150   noit_conf_section_t *listener_configs;
151
152   listener_configs = noit_conf_get_sections(NULL, "/noit/listeners/listener",
153                                             &cnt);
154   noitL(noit_stderr, "Found %d /noit/listeners/listener stanzas\n", cnt);
155   for(i=0; i<cnt; i++) {
156     char address[256];
157     char type[256];
158     unsigned short port;
159     int portint;
160     int backlog;
161     eventer_func_t f;
162
163     if(!noit_conf_get_stringbuf(listener_configs[i],
164                                 "type", type, sizeof(type))) {
165       noitL(noit_stderr, "No type specified in listener stanza %d\n", i+1);
166       continue;
167     }
168     f = eventer_callback_for_name(type);
169     if(!f) {
170       noitL(noit_stderr,
171             "Cannot find handler for listener type: '%s'\n", type);
172       continue;
173     }
174     if(!noit_conf_get_int(listener_configs[i], "port", &portint))
175       portint = 0;
176     port = (unsigned short) portint;
177     if(portint == 0 || (port != portint)) {
178       noitL(noit_stderr,
179             "Invalid port [%d] specified in stanza %d\n", port, i+1);
180       continue;
181     }
182     if(!noit_conf_get_stringbuf(listener_configs[i],
183                                 "address", address, sizeof(address))) {
184       address[0] = '*';
185       address[1] = '\0';
186     }
187     if(!noit_conf_get_int(listener_configs[i], "backlog", &backlog))
188       backlog = 5;
189
190     noit_listener(address, port, SOCK_STREAM, backlog, f, NULL);
191   }
192 }
Note: See TracBrowser for help on using the browser.