WIP: pth transistion, 3rd step, commands basically ported
[rxpd] / src / rxpd_socket.c
1 /*
2     rxpd_socket.c - regex policy daemon
3
4   Copyright (C)
5     2007,               Christian Thaeter <ct@pipapo.org>
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "rxpd.h"
23
24 struct rxpd_socket*
25 rxpd_socket_new_tcp4 (struct rxpd_base* base, const char* addr, unsigned short port)
26 {
27   struct rxpd_socket* self;
28   self = rxpd_malloc (sizeof (struct rxpd_socket));
29
30   self->base = base;
31
32   llist_init (&self->node);
33
34   // TODO all abort() shall become rxpd_die
35   self->fd = socket (PF_INET, SOCK_STREAM, 0);
36   if (self->fd == -1)
37     abort ();
38
39   struct sockaddr_in listen_addr;
40   memset (&listen_addr, 0, sizeof (listen_addr));
41
42   listen_addr.sin_family = AF_INET;
43   if (addr)
44     {
45       if (inet_aton (addr, &listen_addr.sin_addr) == 0)
46         abort();
47     }
48   else
49     listen_addr.sin_addr.s_addr = INADDR_ANY;
50
51   listen_addr.sin_port = htons(port);
52
53   if (bind (self->fd, (struct sockaddr*)&listen_addr, sizeof (listen_addr)) == -1)
54     abort();
55
56   static int yes = 1;
57   if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
58     abort ();
59
60   if (listen (self->fd, 20) == -1)
61     abort ();
62
63   self->rxpd_socket_addr = rxpd_socket_tcp4addr;
64
65   self->accepter = NULL;
66   llist_insert_tail (&base->sockets, &self->node);
67
68   rxpd_log (base, LOG_INFO, "Listening on tcp4:%d\n", port);
69   return self;
70 }
71
72 int
73 rxpd_socket_tcp4addr (struct rxpd_connection* conn, char* dst, const char* pfx, size_t size)
74 {
75   struct sockaddr_in peer;
76   socklen_t len = sizeof (peer);
77   getpeername (conn->fd, (struct sockaddr*)&peer, &len);
78
79   char* addr;
80   addr = inet_ntoa (peer.sin_addr);
81   if (sizeof (":tcp4:") + strlen (pfx) + strlen (addr) > size)
82     return 0;
83
84   strcat (dst, pfx);
85   strcat (dst, ":tcp4:");
86   strcat (dst, addr);
87   return 1;
88 }
89
90 void
91 rxpd_socket_delete (struct rxpd_socket* self)
92 {
93   if (self)
94     {
95       event_del (&self->ev);
96       llist_unlink (&self->node);
97       close (self->fd);
98     }
99   free (self);
100 }
101
102 struct rxpd_socket*
103 rxpd_socket_join (struct rxpd_socket* self)
104 {
105   pth_join (self->accepter, NULL);
106   self->accepter = NULL;
107   return self;
108 }
109
110 struct rxpd_socket*
111 rxpd_socket_spawn (struct rxpd_socket* self)
112 {
113   if (self)
114     {
115       if (self->accepter)
116         rxpd_die ("socket thread already spawned\n");
117
118       self->accepter = pth_spawn (PTH_ATTR_DEFAULT, rxpd_socket_accept, self);
119
120       if (!self->accepter)
121         rxpd_die ("failed spawning thread\n");
122     }
123   return self;
124 }
125
126 void *
127 rxpd_socket_accept (void* ptr)
128 {
129   struct rxpd_socket* self = ptr;
130
131   pth_event_t ev = pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, self->fd);
132
133   rxpd_log (NULL, LOG_NOTICE, "pre ACCEPT\n");
134
135   // TODO cancel thread to leave the loop?
136   while (pth_wait (ev))
137     {
138       rxpd_log (NULL, LOG_NOTICE, "ACCEPT\n");
139
140       struct rxpd_connection* conn =
141         rxpd_connection_new (self);
142       rxpd_connection_spawn (conn);
143     }
144
145   rxpd_log (NULL, LOG_NOTICE, "closed\n");
146
147   return NULL;
148 }
149