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/>.
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;
32 make_server_socket(struct in_addr host_addr
, int port
)
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 (flags
< 0) return twarn("setting O_NONBLOCK"), close(fd
), -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;
60 if (r
== -1) return twarn("listen()"), close(fd
), -1;
62 return listen_socket
= fd
;
70 if (brakes_are_on
) return;
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()");
86 if (!brakes_are_on
) return;
88 if (after_startup
) twarnx("releasing the brakes");
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()");
102 set_main_timeout(time_t deadline
)
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()");