Exemplo n.º 1
0
/*
  shutdown and try to restart a connection to a node after it has been
  disconnected
*/
static void ctdb_tcp_restart(struct ctdb_node *node)
{
    struct ctdb_tcp_node *tnode = talloc_get_type(
                                      node->private_data, struct ctdb_tcp_node);

    DEBUG(DEBUG_NOTICE,("Tearing down connection to dead node :%d\n", node->pnn));

    ctdb_tcp_stop_connection(node);

    tnode->connect_te = tevent_add_timer(node->ctdb->ev, tnode,
                                         timeval_zero(),
                                         ctdb_tcp_node_connect, node);
}
Exemplo n.º 2
0
/*
  called when a complete packet has come in - should not happen on this socket
  unless the other side closes the connection with RST or FIN
 */
void ctdb_tcp_tnode_cb(uint8_t *data, size_t cnt, void *private_data)
{
	struct ctdb_node *node = talloc_get_type(private_data, struct ctdb_node);
	struct ctdb_tcp_node *tnode = talloc_get_type(
		node->private_data, struct ctdb_tcp_node);

	if (data == NULL) {
		node->ctdb->upcalls->node_dead(node);
	}

	ctdb_tcp_stop_connection(node);
	tnode->connect_te = tevent_add_timer(node->ctdb->ev, tnode,
					     timeval_current_ofs(3, 0),
					     ctdb_tcp_node_connect, node);
}
Exemplo n.º 3
0
/*
  called when socket becomes writeable on connect
*/
static void ctdb_node_connect_write(struct tevent_context *ev,
				    struct tevent_fd *fde,
				    uint16_t flags, void *private_data)
{
	struct ctdb_node *node = talloc_get_type(private_data,
						 struct ctdb_node);
	struct ctdb_tcp_node *tnode = talloc_get_type(node->private_data,
						      struct ctdb_tcp_node);
	struct ctdb_context *ctdb = node->ctdb;
	int error = 0;
	socklen_t len = sizeof(error);
	int one = 1;

	talloc_free(tnode->connect_te);
	tnode->connect_te = NULL;

	if (getsockopt(tnode->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0 ||
	    error != 0) {
		ctdb_tcp_stop_connection(node);
		tnode->connect_te = tevent_add_timer(ctdb->ev, tnode,
						    timeval_current_ofs(1, 0),
						    ctdb_tcp_node_connect, node);
		return;
	}

	talloc_free(tnode->connect_fde);
	tnode->connect_fde = NULL;

        if (setsockopt(tnode->fd,IPPROTO_TCP,TCP_NODELAY,(char *)&one,sizeof(one)) == -1) {
		DEBUG(DEBUG_WARNING, ("Failed to set TCP_NODELAY on fd - %s\n",
				      strerror(errno)));
	}
        if (setsockopt(tnode->fd,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one)) == -1) {
		DEBUG(DEBUG_WARNING, ("Failed to set KEEPALIVE on fd - %s\n",
				      strerror(errno)));
	}

	ctdb_queue_set_fd(tnode->out_queue, tnode->fd);

	/* the queue subsystem now owns this fd */
	tnode->fd = -1;
}
Exemplo n.º 4
0
/*
  called when we should try and establish a tcp connection to a node
*/
void ctdb_tcp_node_connect(struct tevent_context *ev, struct tevent_timer *te,
			   struct timeval t, void *private_data)
{
	struct ctdb_node *node = talloc_get_type(private_data,
						 struct ctdb_node);
	struct ctdb_tcp_node *tnode = talloc_get_type(node->private_data, 
						      struct ctdb_tcp_node);
	struct ctdb_context *ctdb = node->ctdb;
        ctdb_sock_addr sock_in;
	int sockin_size;
	int sockout_size;
        ctdb_sock_addr sock_out;

	ctdb_tcp_stop_connection(node);

	sock_out = node->address;

	tnode->fd = socket(sock_out.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
	if (tnode->fd == -1) {
		DEBUG(DEBUG_ERR, (__location__ " Failed to create socket\n"));
		return;
	}
	set_nonblocking(tnode->fd);
	set_close_on_exec(tnode->fd);

	DEBUG(DEBUG_DEBUG, (__location__ " Created TCP SOCKET FD:%d\n", tnode->fd));

	/* Bind our side of the socketpair to the same address we use to listen
	 * on incoming CTDB traffic.
	 * We must specify this address to make sure that the address we expose to
	 * the remote side is actually routable in case CTDB traffic will run on
	 * a dedicated non-routeable network.
	 */
	sock_in = *ctdb->address;

	/* AIX libs check to see if the socket address and length
	   arguments are consistent with each other on calls like
	   connect().   Can not get by with just sizeof(sock_in),
	   need sizeof(sock_in.ip).
	*/
	switch (sock_in.sa.sa_family) {
	case AF_INET:
		sock_in.ip.sin_port = 0 /* Any port */;
		sockin_size = sizeof(sock_in.ip);
		sockout_size = sizeof(sock_out.ip);
		break;
	case AF_INET6:
		sock_in.ip6.sin6_port = 0 /* Any port */;
		sockin_size = sizeof(sock_in.ip6);
		sockout_size = sizeof(sock_out.ip6);
		break;
	default:
		DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n",
			sock_in.sa.sa_family));
		close(tnode->fd);
		return;
	}

	if (bind(tnode->fd, (struct sockaddr *)&sock_in, sockin_size) == -1) {
		DEBUG(DEBUG_ERR, (__location__ " Failed to bind socket %s(%d)\n",
				  strerror(errno), errno));
		close(tnode->fd);
		return;
	}

	if (connect(tnode->fd, (struct sockaddr *)&sock_out, sockout_size) != 0 &&
	    errno != EINPROGRESS) {
		ctdb_tcp_stop_connection(node);
		tnode->connect_te = tevent_add_timer(ctdb->ev, tnode,
						     timeval_current_ofs(1, 0),
						     ctdb_tcp_node_connect, node);
		return;
	}

	/* non-blocking connect - wait for write event */
	tnode->connect_fde = tevent_add_fd(node->ctdb->ev, tnode, tnode->fd,
					   TEVENT_FD_WRITE|TEVENT_FD_READ,
					   ctdb_node_connect_write, node);

	/* don't give it long to connect - retry in one second. This ensures
	   that we find a node is up quickly (tcp normally backs off a syn reply
	   delay by quite a lot) */
	tnode->connect_te = tevent_add_timer(ctdb->ev, tnode,
					     timeval_current_ofs(1, 0),
					     ctdb_tcp_node_connect, node);
}