4 Copyright (C) Andrew Tridgell 2006
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "lib/events/events.h"
23 #include "lib/tdb/include/tdb.h"
24 #include "system/network.h"
25 #include "system/filesys.h"
26 #include "../include/ctdb_private.h"
29 static void set_nonblocking(int fd
)
32 v
= fcntl(fd
, F_GETFL
, 0);
33 fcntl(fd
, F_SETFL
, v
| O_NONBLOCK
);
38 called when socket becomes writeable on connect
40 static void ctdb_node_connect_write(struct event_context
*ev
, struct fd_event
*fde
,
41 uint16_t flags
, void *private)
43 struct ctdb_node
*node
= talloc_get_type(private, struct ctdb_node
);
44 struct ctdb_tcp_node
*tnode
= talloc_get_type(node
->private,
45 struct ctdb_tcp_node
);
46 struct ctdb_context
*ctdb
= node
->ctdb
;
48 socklen_t len
= sizeof(error
);
50 if (getsockopt(tnode
->fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
) != 0 ||
55 event_add_timed(ctdb
->ev
, node
, timeval_current_ofs(1, 0),
56 ctdb_tcp_node_connect
, node
);
61 tnode
->fde
= event_add_fd(node
->ctdb
->ev
, node
, tnode
->fd
, EVENT_FD_READ
,
62 ctdb_tcp_node_write
, node
);
64 /* tell the ctdb layer we are connected */
65 node
->ctdb
->upcalls
->node_connected(node
);
68 EVENT_FD_WRITEABLE(tnode
->fde
);
73 called when we should try and establish a tcp connection to a node
75 void ctdb_tcp_node_connect(struct event_context
*ev
, struct timed_event
*te
,
76 struct timeval t
, void *private)
78 struct ctdb_node
*node
= talloc_get_type(private, struct ctdb_node
);
79 struct ctdb_tcp_node
*tnode
= talloc_get_type(node
->private,
80 struct ctdb_tcp_node
);
81 struct ctdb_context
*ctdb
= node
->ctdb
;
82 struct sockaddr_in sock_out
;
84 tnode
->fd
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
86 set_nonblocking(tnode
->fd
);
88 inet_pton(AF_INET
, node
->address
.address
, &sock_out
.sin_addr
);
89 sock_out
.sin_port
= htons(node
->address
.port
);
90 sock_out
.sin_family
= PF_INET
;
92 if (connect(tnode
->fd
, (struct sockaddr
*)&sock_out
, sizeof(sock_out
)) != 0 &&
93 errno
!= EINPROGRESS
) {
94 /* try again once a second */
96 event_add_timed(ctdb
->ev
, node
, timeval_current_ofs(1, 0),
97 ctdb_tcp_node_connect
, node
);
101 /* non-blocking connect - wait for write event */
102 event_add_fd(node
->ctdb
->ev
, node
, tnode
->fd
, EVENT_FD_WRITE
|EVENT_FD_READ
,
103 ctdb_node_connect_write
, node
);
107 destroy a ctdb_incoming structure
109 static int ctdb_incoming_destructor(struct ctdb_incoming
*in
)
117 called when we get contacted by another node
118 currently makes no attempt to check if the connection is really from a ctdb
121 static void ctdb_listen_event(struct event_context
*ev
, struct fd_event
*fde
,
122 uint16_t flags
, void *private)
124 struct ctdb_context
*ctdb
;
125 struct ctdb_tcp
*ctcp
;
126 struct sockaddr_in addr
;
129 struct ctdb_incoming
*in
;
131 ctdb
= talloc_get_type(private, struct ctdb_context
);
132 ctcp
= talloc_get_type(ctdb
->private, struct ctdb_tcp
);
133 memset(&addr
, 0, sizeof(addr
));
135 fd
= accept(ctcp
->listen_fd
, (struct sockaddr
*)&addr
, &len
);
136 if (fd
== -1) return;
138 in
= talloc_zero(ctdb
, struct ctdb_incoming
);
142 set_nonblocking(in
->fd
);
144 event_add_fd(ctdb
->ev
, in
, in
->fd
, EVENT_FD_READ
,
145 ctdb_tcp_incoming_read
, in
);
147 talloc_set_destructor(in
, ctdb_incoming_destructor
);
152 listen on our own address
154 int ctdb_tcp_listen(struct ctdb_context
*ctdb
)
156 struct ctdb_tcp
*ctcp
= talloc_get_type(ctdb
->private, struct ctdb_tcp
);
157 struct sockaddr_in sock
;
160 sock
.sin_port
= htons(ctdb
->address
.port
);
161 sock
.sin_family
= PF_INET
;
162 inet_pton(AF_INET
, ctdb
->address
.address
, &sock
.sin_addr
);
164 ctcp
->listen_fd
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
165 if (ctcp
->listen_fd
== -1) {
166 ctdb_set_error(ctdb
, "socket failed\n");
170 setsockopt(ctcp
->listen_fd
,SOL_SOCKET
,SO_REUSEADDR
,(char *)&one
,sizeof(one
));
172 if (bind(ctcp
->listen_fd
, (struct sockaddr
* )&sock
, sizeof(sock
)) != 0) {
173 ctdb_set_error(ctdb
, "bind failed\n");
174 close(ctcp
->listen_fd
);
175 ctcp
->listen_fd
= -1;
179 if (listen(ctcp
->listen_fd
, 10) == -1) {
180 ctdb_set_error(ctdb
, "listen failed\n");
181 close(ctcp
->listen_fd
);
182 ctcp
->listen_fd
= -1;
186 event_add_fd(ctdb
->ev
, ctdb
, ctcp
->listen_fd
, EVENT_FD_READ
,
187 ctdb_listen_event
, ctdb
);