Oops, ensure the copy gets freed.
[beanstalkd.git] / net.c
blob05ac52b187096f4c99de34b5933b27fe2c0886d6
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;
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 (flags < 0) 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 /*memset(&addr, 0, sizeof addr);*/
55 addr.sin_family = AF_INET;
56 addr.sin_port = htons(port);
57 addr.sin_addr = host_addr;
58 r = bind(fd, (struct sockaddr *) &addr, sizeof addr);
59 if (r == -1) return twarn("bind()"), close(fd), -1;
61 r = listen(fd, 1024);
62 if (r == -1) return twarn("listen()"), close(fd), -1;
64 return listen_socket = fd;
67 void
68 brake()
70 int r;
72 if (brakes_are_on) return;
73 brakes_are_on = 1;
74 twarnx("too many connections; putting on the brakes");
76 r = event_del(&listen_evq);
77 if (r == -1) twarn("event_del()");
79 r = listen(listen_socket, 0);
80 if (r == -1) twarn("listen()");
83 void
84 unbrake(evh h)
86 int r;
88 if (!brakes_are_on) return;
89 brakes_are_on = 0;
90 if (after_startup) twarnx("releasing the brakes");
91 after_startup = 1;
93 accept_handler = h ? : accept_handler;
94 event_set(&listen_evq, listen_socket, EV_READ | EV_PERSIST,
95 accept_handler, &listen_evq);
97 set_main_timeout(main_deadline);
99 r = listen(listen_socket, 1024);
100 if (r == -1) twarn("listen()");
103 void
104 set_main_timeout(time_t deadline)
106 int r;
107 struct timeval tv = {deadline - time(NULL), 0};
109 main_deadline = deadline;
110 r = event_add(&listen_evq, deadline ? &tv : NULL);
111 if (r == -1) twarn("event_add()");