cleaned up some code, removed/improved few comments, better logging
[rxpd.git] / src / rxpd_socket.c
blob4f81960ea345060f4ead369d594cf7821636a204
1 /*
2 rxpd_socket.c - regex policy daemon
4 Copyright (C)
5 2007, Christian Thaeter <ct@pipapo.org>
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.
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.
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.
22 #include "rxpd.h"
24 struct rxpd_socket*
25 rxpd_socket_new_tcp4 (struct rxpd_base* base, const char* addr, unsigned short port)
27 struct rxpd_socket* self;
28 self = rxpd_malloc (sizeof (struct rxpd_socket));
30 self->base = base;
32 llist_init (&self->node);
34 self->fd = socket (PF_INET, SOCK_STREAM, 0);
35 if (self->fd == -1)
36 goto esocket;
38 struct sockaddr_in listen_addr;
39 memset (&listen_addr, 0, sizeof (listen_addr));
41 listen_addr.sin_family = AF_INET;
42 if (addr)
44 if (inet_aton (addr, &listen_addr.sin_addr) == 0)
45 goto esocket;
47 else
48 listen_addr.sin_addr.s_addr = INADDR_ANY;
50 listen_addr.sin_port = htons(port);
52 if (bind (self->fd, (struct sockaddr*)&listen_addr, sizeof (listen_addr)) == -1)
53 goto esocket;
55 static int yes = 1;
56 if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
57 goto esocket;
59 if (listen (self->fd, 20) == -1)
60 goto esocket;
62 self->rxpd_socket_addr = rxpd_socket_tcp4addr;
64 self->accepter = NULL;
65 llist_insert_tail (&base->sockets, &self->node);
67 rxpd_log (base, LOG_INFO, "Listening on tcp4:%d\n", port);
68 return self;
70 esocket:
71 rxpd_die ("failed creating socket\n");
72 /* free (self); rxpd_die never returns */
73 return NULL;
76 int
77 rxpd_socket_tcp4addr (struct rxpd_connection* conn, char* dst, const char* pfx, size_t size)
79 struct sockaddr_in peer;
80 socklen_t len = sizeof (peer);
81 getpeername (conn->fd, (struct sockaddr*)&peer, &len);
83 char* addr;
84 addr = inet_ntoa (peer.sin_addr);
85 if (sizeof (":tcp4:") + strlen (pfx) + strlen (addr) > size)
86 return 0;
88 strcat (dst, pfx);
89 strcat (dst, ":tcp4:");
90 strcat (dst, addr);
91 return 1;
94 void
95 rxpd_socket_delete (struct rxpd_socket* self)
97 if (self)
99 llist_unlink (&self->node);
100 close (self->fd);
102 free (self);
105 struct rxpd_socket*
106 rxpd_socket_join (struct rxpd_socket* self)
108 pth_join (self->accepter, NULL);
109 self->accepter = NULL;
110 return self;
113 struct rxpd_socket*
114 rxpd_socket_spawn (struct rxpd_socket* self)
116 if (self)
118 if (self->accepter)
119 rxpd_die ("socket thread already spawned\n");
121 self->accepter = pth_spawn (PTH_ATTR_DEFAULT, rxpd_socket_accept, self);
123 if (!self->accepter)
124 rxpd_die ("failed spawning thread\n");
126 return self;
129 struct rxpd_socket*
130 rxpd_socket_cancel (struct rxpd_socket* self)
132 pth_cancel (self->accepter);
133 return self;
136 void *
137 rxpd_socket_accept (void* ptr)
139 struct rxpd_socket* self = ptr;
141 pth_event_t ev = pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, self->fd);
143 while (pth_wait (ev))
145 int fd = pth_accept (self->fd, NULL, 0);
146 if (fd == -1)
147 rxpd_die ("error accepting connection\n");
149 struct rxpd_connection* conn = rxpd_connection_new (self, fd);
151 char buf[512];
153 if (rxpd_socket_tcp4addr (conn, buf, "", 511))
155 rxpd_log (self->base, LOG_INFO, "incoming connection '%s'\n", buf);
156 rxpd_connection_spawn (conn);
158 else
159 rxpd_log (self->base, LOG_ERR, "illegal hostname\n", buf);
162 rxpd_log (NULL, LOG_NOTICE, "closed\n");
163 return NULL;