]> rtime.felk.cvut.cz Git - frescor/forb.git/blob - src/proto_unix.c
e6c79815dd2624ec91286e8bef5f595e132e770d
[frescor/forb.git] / src / proto_unix.c
1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                 */
4 /*                                                                        */
5 /*   Universidad de Cantabria,              SPAIN                         */
6 /*   University of York,                    UK                            */
7 /*   Scuola Superiore Sant'Anna,            ITALY                         */
8 /*   Kaiserslautern University,             GERMANY                       */
9 /*   Univ. Politécnica  Valencia,           SPAIN                        */
10 /*   Czech Technical University in Prague,  CZECH REPUBLIC                */
11 /*   ENEA                                   SWEDEN                        */
12 /*   Thales Communication S.A.              FRANCE                        */
13 /*   Visual Tools S.A.                      SPAIN                         */
14 /*   Rapita Systems Ltd                     UK                            */
15 /*   Evidence                               ITALY                         */
16 /*                                                                        */
17 /*   See http://www.frescor.org for a link to partners' websites          */
18 /*                                                                        */
19 /*          FRESCOR project (FP6/2005/IST/5-034026) is funded             */
20 /*       in part by the European Union Sixth Framework Programme          */
21 /*       The European Union is not liable of any use that may be          */
22 /*       made of this code.                                               */
23 /*                                                                        */
24 /*                                                                        */
25 /*  This file is part of FORB (Frescor Object Request Broker)             */
26 /*                                                                        */
27 /* FORB is free software; you can redistribute it and/or modify it        */
28 /* under terms of the GNU General Public License as published by the      */
29 /* Free Software Foundation; either version 2, or (at your option) any    */
30 /* later version.  FORB is distributed in the hope that it will be        */
31 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
32 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
33 /* General Public License for more details. You should have received a    */
34 /* copy of the GNU General Public License along with FORB; see file       */
35 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
36 /* Cambridge, MA 02139, USA.                                              */
37 /*                                                                        */
38 /* As a special exception, including FORB header files in a file,         */
39 /* instantiating FORB generics or templates, or linking other files       */
40 /* with FORB objects to produce an executable application, does not       */
41 /* by itself cause the resulting executable application to be covered     */
42 /* by the GNU General Public License. This exception does not             */
43 /* however invalidate any other reasons why the executable file might be  */
44 /* covered by the GNU Public License.                                     */
45 /**************************************************************************/
46
47 #include <dirent.h>
48 #include "proto.h"
49 #include <forb/proto_unix.h>
50 #include <stdio.h>
51 #include <sys/socket.h>
52 #include <sys/types.h>
53 #include <sys/un.h>
54
55 typedef struct sockaddr_un unix_addr_t;
56
57 /** UNIX protocol data for ports. */
58 struct unix_port {
59         int socket;
60         unix_addr_t addr;
61 };
62
63 static struct unix_port*
64 peer_to_uport(forb_peer_t *peer) { return peer->port->proto_priv; }
65
66 static void
67 unix_server_to_addr(unix_addr_t *addr, const forb_server_id *server)
68 {
69         char str[65];
70         addr->sun_family = AF_UNIX;
71         sprintf(addr->sun_path, "/tmp/forb-%s",
72                 forb_uuid_to_string(str, (forb_uuid_t*)server->uuid, sizeof(str)));
73 }
74
75 static size_t
76 unix_send(forb_peer_t *peer, const void *buf, size_t len)
77 {
78         unix_addr_t addr;
79         struct unix_port *p = peer_to_uport(peer);
80         //printf("send to %s\n", c->addr.sun_path);
81         unix_server_to_addr(&addr, &peer->server_id);
82         return sendto(p->socket, buf, len, 0,
83                       (struct sockaddr*)&addr, sizeof(addr));
84 }
85
86 static size_t
87 unix_recv(forb_port_t *port, void *buf, size_t len)
88 {
89         struct unix_port *p = port->proto_priv;
90         return recv(p->socket, buf, len, 0);
91 }
92
93 static int
94 unix_port_destroy(forb_port_t * port)
95 {
96         struct unix_port *pd = port->proto_priv;
97         unix_addr_t addr;
98         socklen_t len = sizeof(addr);
99         getsockname(pd->socket, (struct sockaddr*)&addr, &len);
100         if (addr.sun_family == AF_UNIX)
101                 unlink(addr.sun_path);
102         close(pd->socket);
103         forb_free(pd);
104         return 0;
105 }
106
107 static size_t
108 unix_broadcast(forb_port_t *port, const void *buf, size_t len)
109 {
110         struct unix_port *p = port->proto_priv;
111         DIR *dir;
112         struct dirent *dirent;
113         unix_addr_t addr;
114         int ret;
115         int success = 0;
116         
117         dir = opendir("/tmp");
118         if (!dir) return -errno;
119
120         addr.sun_family = AF_UNIX;
121         
122         while ((dirent = readdir(dir))) {
123                 bool forb_socket = 
124 #ifdef _DIRENT_HAVE_D_TYPE
125                         (dirent->d_type == DT_SOCK ||
126                          dirent->d_type == DT_UNKNOWN) &&
127 #endif
128                         (strncmp(dirent->d_name, "forb-", 5) == 0);
129                 
130 /*              printf("d_name=%s d_type=%d (%d)\n", dirent->d_name, dirent->d_type, DT_SOCK); */
131                 if (forb_socket)
132                 {
133                         strcpy(addr.sun_path, "/tmp/");
134                         strncat(addr.sun_path, dirent->d_name, sizeof(addr.sun_path));
135 /*                      printf("Broadcasting to %s\n", addr.sun_path); */
136                         ret = sendto(p->socket, buf, len, 0,
137                                      (struct sockaddr*)&addr, sizeof(addr));
138                         /* We do not care about errors in brodcasts -
139                          * the socket may nomore be active */
140                         if (ret == len) {
141                                 success++;
142                         } else {
143 /*                              perror("unix_broadcast"); */
144 /*                              return ret; */
145                         }
146                 }
147                         
148         }
149         closedir(dir);
150         if (success) {
151                 ret = len;
152         } else {
153                 ret = -1;
154         }
155         return ret;
156 }
157
158 static const forb_proto_t proto_unix = {
159         .hello_interval = 40 /* seconds */,
160         .port_destroy = unix_port_destroy,
161         .peer_destroy = NULL,
162         .send = unix_send,
163         .recv = unix_recv,
164         .broadcast = unix_broadcast,
165         /* We do not need the following functions, sice the address
166          * can be derived from server_id */
167         .serialize_addr = NULL,
168         .deserialize_addr = NULL,
169 };
170
171 /** 
172  * Initializes UNIX protocol port.
173  * 
174  * @param port Port to initialize.
175  * @param server Server this port belongs to.
176  * 
177  * @return Zero on success, -1 on error and errno is set
178  * appropriately.
179  */
180 int
181 forb_unix_port_init(forb_port_t *port, const forb_server_id *server)
182 {
183         
184         int ret;       
185         struct unix_port *pd;
186
187         pd = forb_malloc(sizeof(*pd));
188         if (!pd)
189                 return -1;
190         
191         pd->socket = socket(PF_UNIX, SOCK_DGRAM, 0);
192         if (pd->socket == -1) goto err1;
193
194         unix_server_to_addr(&pd->addr, server);
195         /* unlink(pd->addr.sun_path); */ /* TODO: What to do when the socket already exist? */
196         ret = bind(pd->socket, (struct sockaddr*)&pd->addr, sizeof(pd->addr));
197         if (ret == -1) goto err;
198
199         port->proto = &proto_unix;
200         port->proto_priv = pd;
201         return 0;
202 err:
203         ret = errno;
204         close(pd->socket);
205         errno = ret;
206 err1:
207         ret = errno;
208         forb_free(pd);
209         errno = ret;
210         return -1;
211 }