Update comment.
[beanstalkd.git] / net.c
blob4da58449b82d676a5bf7ff5d80f13acedfaac3e7
1 /* net.c - stupid boilerplate shit that I shouldn't have to write */
3 /* Copyright (C) 2007 Keith Rarick and Philotic Inc.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <stdio.h>
20 #include <errno.h>
22 #include "net.h"
23 #include "util.h"
25 static int listen_socket = -1;
26 static struct event listen_evq;
27 static evh accept_handler;
28 static time_t main_deadline = 0;
29 static int brakes_are_on = 1, after_startup = 0;
31 int
32 make_server_socket(struct in_addr host_addr, int port)
34 int fd, flags, r;
35 struct linger linger = {0, 0};
36 struct sockaddr_in addr = {}; /* initialize to 0 */
38 fd = socket(AF_INET, SOCK_STREAM, 0);
39 if (fd == -1) return twarn("socket()"), -1;
41 flags = fcntl(fd, F_GETFL, 0);
42 if (flags < 0) return twarn("getting flags"), close(fd), -1;
44 r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
45 if (r == -1) return twarn("setting O_NONBLOCK"), close(fd), -1;
47 flags = 1;
48 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof flags);
49 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof flags);
50 setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, sizeof linger);
51 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof flags);
53 addr.sin_family = AF_INET;
54 addr.sin_port = htons(port);
55 addr.sin_addr = host_addr;
56 r = bind(fd, (struct sockaddr *) &addr, sizeof addr);
57 if (r == -1) return twarn("bind()"), close(fd), -1;
59 r = listen(fd, 1024);
60 if (r == -1) return twarn("listen()"), close(fd), -1;
62 return listen_socket = fd;
65 void
66 brake()
68 int r;
70 if (brakes_are_on) return;
71 brakes_are_on = 1;
72 twarnx("too many connections; putting on the brakes");
74 r = event_del(&listen_evq);
75 if (r == -1) twarn("event_del()");
77 r = listen(listen_socket, 0);
78 if (r == -1) twarn("listen()");
81 void
82 unbrake(evh h)
84 int r;
86 if (!brakes_are_on) return;
87 brakes_are_on = 0;
88 if (after_startup) twarnx("releasing the brakes");
89 after_startup = 1;
91 accept_handler = h ? : accept_handler;
92 event_set(&listen_evq, listen_socket, EV_READ | EV_PERSIST,
93 accept_handler, &listen_evq);
95 set_main_timeout(main_deadline);
97 r = listen(listen_socket, 1024);
98 if (r == -1) twarn("listen()");
101 void
102 set_main_timeout(time_t deadline)
104 int r;
105 struct timeval tv = {deadline - time(NULL), 0};
107 main_deadline = deadline;
108 r = event_add(&listen_evq, deadline ? &tv : NULL);
109 if (r == -1) twarn("event_add()");