Add to git.
[pthrlib.git] / src / pthr_listener.c
1 /* Listener thread.
2  *
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Library General Public
5  * License as published by the Free Software Foundation; either
6  * version 2 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Library General Public License for more details.
12  *
13  * You should have received a copy of the GNU Library General Public
14  * License along with this library; if not, write to the Free
15  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: pthr_listener.c,v 1.5 2002/12/08 13:41:07 rich Exp $
18  */
19
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #ifdef HAVE_FCNTL_H
26 #include <fcntl.h>
27 #endif
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #ifdef HAVE_SYS_SOCKET_H
34 #include <sys/socket.h>
35 #endif
36
37 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h>
39 #endif
40
41 #ifdef HAVE_ARPA_INET_H
42 #include <arpa/inet.h>
43 #endif
44
45 #ifdef HAVE_SYSLOG_H
46 #include <syslog.h>
47 #endif
48
49 #include "pthr_pseudothread.h"
50 #include "pthr_listener.h"
51
52 struct listener
53 {
54   pseudothread pth;
55   int sock;
56   void (*processor_fn) (int sock, void *data);
57   void *data;
58 };
59
60 static void run (void *vp);
61
62 listener
63 new_listener (int sock,
64               void (*processor_fn) (int sock, void *data), void *data)
65 {
66   pool pool;
67   listener p;
68
69   pool = new_pool ();
70   p = pmalloc (pool, sizeof *p);
71
72   p->sock = sock;
73   p->processor_fn = processor_fn;
74   p->data = data;
75   p->pth = new_pseudothread (pool, run, p, "listener");
76
77   pth_start (p->pth);
78
79   return p;
80 }
81
82 static void
83 run (void *vp)
84 {
85   listener p = (listener) vp;
86
87   for (;;)
88     {
89       struct sockaddr_in addr;
90       int sz, ns;
91
92       /* Wait for the new connection. */
93       sz = sizeof addr;
94       ns = pth_accept (p->sock, (struct sockaddr *) &addr, &sz);
95
96       if (ns < 0) { perror ("accept"); continue; }
97
98       /* Set the new socket to non-blocking. */
99       if (fcntl (ns, F_SETFL, O_NONBLOCK) < 0) abort ();
100
101       /* Create a new processor thread to handle this connection. */
102       p->processor_fn (ns, p->data);
103     }
104 }