added gentoo ebuilds
[libmixp.git] / libmixp / server.c
blob72b2632beec970c0c8f18c24bd458e91ba24e0cf
1 /* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
2 * See LICENSE file for license details.
3 */
4 #include <assert.h>
5 #include <errno.h>
6 #include <stdlib.h>
7 #include <sys/socket.h>
8 #include <sys/signal.h>
9 #include <netinet/in.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include "mixp_local.h"
14 int ixp_serversock_tcp(const char* addr, int port, char** errstr)
16 int fd;
17 struct sockaddr_in in_addr;
19 signal(SIGPIPE,SIG_IGN);
20 if ((fd=socket(AF_INET, SOCK_STREAM, 0))<0)
22 *errstr = "cannot open socket";
23 return -1;
26 in_addr.sin_family = AF_INET;
27 in_addr.sin_port = htons(port);
28 in_addr.sin_addr.s_addr = htonl(INADDR_ANY);
30 if (bind(fd,(struct sockaddr*)&in_addr, sizeof(struct sockaddr_in))<0)
32 *errstr = "cannot bind socket";
33 close(fd);
34 return -1;
37 if (listen(fd, IXP_MAX_CACHE)<0)
39 *errstr = "cannot listen on socket";
40 close(fd);
41 return -1;
44 return fd;
47 MIXP_CONNECTION *
48 ixp_listen(MIXP_SERVER *s, int fd, void *aux,
49 void (*read)(MIXP_CONNECTION *c),
50 void (*close)(MIXP_CONNECTION *c)
51 ) {
52 MIXP_CONNECTION *c;
54 if (s==NULL)
56 fprintf(stderr,"ixp_listen() NULL server struct passed\n");
57 return NULL;
60 c = calloc(1,sizeof(MIXP_CONNECTION));
61 c->fd = fd;
62 c->aux = aux;
63 c->srv = s;
64 c->read = read;
65 c->close = close;
66 c->next = s->conn;
67 s->conn = c;
68 return c;
71 void
72 ixp_hangup(MIXP_CONNECTION *c) {
73 MIXP_SERVER *s;
74 MIXP_CONNECTION **tc;
76 s = c->srv;
77 for(tc=&s->conn; *tc; tc=&(*tc)->next)
78 if(*tc == c) break;
79 assert(*tc == c);
81 *tc = c->next;
82 c->closed = 1;
83 if(c->close)
84 c->close(c);
85 else
86 shutdown(c->fd, SHUT_RDWR);
88 close(c->fd);
89 free(c);
92 static void
93 prepare_select(MIXP_SERVER *s) {
94 MIXP_CONNECTION *c;
96 FD_ZERO(&s->rd);
97 for(c = s->conn; c; c = c->next)
98 if(c->read) {
99 if(s->maxfd < c->fd)
100 s->maxfd = c->fd;
101 FD_SET(c->fd, &s->rd);
105 static void
106 handle_conns(MIXP_SERVER *s) {
107 MIXP_CONNECTION *c, *n;
108 for(c = s->conn; c; c = n) {
109 n = c->next;
110 if(FD_ISSET(c->fd, &s->rd))
111 c->read(c);
115 char *
116 ixp_serverloop(MIXP_SERVER *s) {
117 int r;
119 s->running = 1;
120 while(s->running) {
121 if(s->preselect)
122 s->preselect(s);
123 prepare_select(s);
124 r = select(s->maxfd + 1, &s->rd, 0, 0, 0);
125 if(r < 0) {
126 if(errno == EINTR)
127 continue;
128 return "fatal select error";
130 handle_conns(s);
132 return NULL;
135 void
136 ixp_server_close(MIXP_SERVER *s) {
137 MIXP_CONNECTION *c, *next;
138 for(c = s->conn; c; c = next) {
139 next = c->next;
140 ixp_hangup(c);