Esempio n. 1
0
/**
 * accept a connection
 *
 * event handler for listening connections
 *
 * @param srv    a listening socket 
 * 
 */
network_socket *network_socket_accept(network_socket *srv) {
	network_socket *client;

	g_return_val_if_fail(srv, NULL);
	g_return_val_if_fail(srv->socket_type == SOCK_STREAM, NULL); /* accept() only works on stream sockets */

	client = network_socket_new();
    if (-1 == (client->fd = accept4(srv->fd, &client->src->addr.common, &(client->src->len), SOCK_NONBLOCK))) {
        network_socket_free(client);

        return NULL;
    }

	if (network_address_refresh_name(client->src)) {
		network_socket_free(client);
		return NULL;
	}

	/* the listening side may be INADDR_ANY, let's get which address the client really connected to */
	if (-1 == getsockname(client->fd, &client->dst->addr.common, &(client->dst->len))) {
		network_address_reset(client->dst);
	} else if (network_address_refresh_name(client->dst)) {
		network_address_reset(client->dst);
	}

	return client;
}
Esempio n. 2
0
/**
 * init the plugin with the parsed config
 */
static int network_mysqld_admin_plugin_apply_config(chassis *chas, chassis_plugin_config *config) {
    network_mysqld_con *con;
    network_socket *listen_sock;

    if (!config->address) config->address = g_strdup(":4041");
    if (!config->admin_username) {
        g_critical("%s: --admin-username needs to be set",
                   G_STRLOC);
        return -1;
    }
    if (!config->admin_password) {
        g_critical("%s: --admin-password needs to be set",
                   G_STRLOC);
        return -1;
    }
    if (!config->lua_script) {
        g_critical("%s: --admin-lua-script needs to be set, <install-dir>/lib/mysql-proxy/lua/admin.lua may be a good value",
                   G_STRLOC);
        return -1;
    }


    /**
     * create a connection handle for the listen socket
     */
    con = network_mysqld_con_new();
    network_mysqld_add_connection(chas, con);
    con->config = config;

    config->listen_con = con;

    listen_sock = network_socket_new();
    con->server = listen_sock;

    /* set the plugin hooks as we want to apply them to the new connections too later */
    network_mysqld_server_connection_init(con);

    /* FIXME: network_socket_set_address() */
    if (0 != network_address_set_address(listen_sock->dst, config->address)) {
        return -1;
    }

    /* FIXME: network_socket_bind() */
    if (0 != network_socket_bind(listen_sock)) {
        return -1;
    }

    /**
     * call network_mysqld_con_accept() with this connection when we are done
     */
    event_set(&(listen_sock->event), listen_sock->fd, EV_READ|EV_PERSIST, network_mysqld_con_accept, con);
    event_base_set(chas->event_base, &(listen_sock->event));
    event_add(&(listen_sock->event), NULL);

    return 0;
}
Esempio n. 3
0
/**
 * init the plugin with the parsed config
 */
static int network_mysqld_master_plugin_apply_config(chassis *chas, chassis_plugin_config *config) {
    network_mysqld_con *con;
    network_socket *listen_sock;

    if (!config->address) config->address = g_strdup(":4041");
    if (!config->master_username) config->master_username = g_strdup("root");
    if (!config->master_password) config->master_password = g_strdup("secret");

    /**
     * create a connection handle for the listen socket
     */
    con = network_mysqld_con_new();
    network_mysqld_add_connection(chas, con);
    con->config = config;

    config->listen_con = con;

    listen_sock = network_socket_new();
    con->server = listen_sock;

    /* set the plugin hooks as we want to apply them to the new connections too later */
    network_mysqld_server_connection_init(con);

    /* FIXME: network_socket_set_address() */
    if (0 != network_address_set_address(listen_sock->dst, config->address)) {
        return -1;
    }

    /* FIXME: network_socket_bind() */
    if (0 != network_socket_bind(listen_sock)) {
        return -1;
    }

    /**
     * call network_mysqld_con_accept() with this connection when we are done
     */
    event_set(&(listen_sock->event), listen_sock->fd, EV_READ|EV_PERSIST, network_mysqld_con_accept, con);
    event_base_set(chas->event_base, &(listen_sock->event));
    event_add(&(listen_sock->event), NULL);

    return 0;
}
Esempio n. 4
0
network_socket *network_socket_init() {
	return network_socket_new();
}
Esempio n. 5
0
network_socket *self_connect(network_mysqld_con *con, network_backend_t *backend, GHashTable *pwd_table) {

    /*make sure that the max conn for the backend is no more than the config number
     *when max_conn_for_a_backend is no more than 0, there is no limitation for max connection for a backend;
     * */
    if (con->srv->max_conn_for_a_backend > 0 && backend->connected_clients >= con->srv->max_conn_for_a_backend) {
        g_critical("%s.%d: self_connect:%08x's connected_clients is %d, which are too many!",__FILE__, __LINE__, backend,  backend->connected_clients);
        return NULL;
    }
    
    //1. connect DB
	network_socket *sock = network_socket_new();
	network_address_copy(sock->dst, backend->addr);
	if (-1 == (sock->fd = socket(sock->dst->addr.common.sa_family, sock->socket_type, 0))) {
		g_critical("%s.%d: socket(%s) failed: %s (%d)", __FILE__, __LINE__, sock->dst->name->str, g_strerror(errno), errno);
		network_socket_free(sock);
		return NULL;
	}
	if (-1 == (connect(sock->fd, &sock->dst->addr.common, sock->dst->len))) {
		g_message("%s.%d: connecting to backend (%s) failed, marking it as down for ...", __FILE__, __LINE__, sock->dst->name->str);
		network_socket_free(sock);
		if (backend->state != BACKEND_STATE_OFFLINE) backend->state = BACKEND_STATE_DOWN;
		return NULL;
	}

	//2. read handshake,重点是获取20个字节的随机串
	off_t to_read = NET_HEADER_SIZE;
	guint offset = 0;
	guchar header[NET_HEADER_SIZE];
	while (to_read > 0) {
		gssize len = recv(sock->fd, header + offset, to_read, 0);
		if (len == -1 || len == 0) {
			network_socket_free(sock);
			return NULL;
		}
		offset += len;
		to_read -= len;
	}

	to_read = header[0] + (header[1] << 8) + (header[2] << 16);
	offset = 0;
	GString *data = g_string_sized_new(to_read);
	while (to_read > 0) {
		gssize len = recv(sock->fd, data->str + offset, to_read, 0);
		if (len == -1 || len == 0) {
			network_socket_free(sock);
			g_string_free(data, TRUE);
			return NULL;
		}
		offset += len;
		to_read -= len;
	}
	data->len = offset;

	network_packet packet;
	packet.data = data;
	packet.offset = 0;
	network_mysqld_auth_challenge *challenge = network_mysqld_auth_challenge_new();
	network_mysqld_proto_get_auth_challenge(&packet, challenge);

	//3. 生成response
	GString *response = g_string_sized_new(20);
	GString *hashed_password = g_hash_table_lookup(pwd_table, con->client->response->username->str);
	if (hashed_password) {
		network_mysqld_proto_password_scramble(response, S(challenge->challenge), S(hashed_password));
	} else {
		network_socket_free(sock);
		g_string_free(data, TRUE);
		network_mysqld_auth_challenge_free(challenge);
		g_string_free(response, TRUE);
		return NULL;
	}

	//4. send auth
	off_t to_write = 58 + con->client->response->username->len;
	offset = 0;
	g_string_truncate(data, 0);
	char tmp[] = {to_write - 4, 0, 0, 1, 0x85, 0xa6, 3, 0, 0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	g_string_append_len(data, tmp, 36);
	g_string_append_len(data, con->client->response->username->str, con->client->response->username->len);
	g_string_append_len(data, "\0\x14", 2);
	g_string_append_len(data, response->str, 20);
	g_string_free(response, TRUE);
	while (to_write > 0) {
		gssize len = send(sock->fd, data->str + offset, to_write, 0);
		if (len == -1) {
			network_socket_free(sock);
			g_string_free(data, TRUE);
			network_mysqld_auth_challenge_free(challenge);
			return NULL;
		}
		offset += len;
		to_write -= len;
	}

	//5. read auth result
	to_read = NET_HEADER_SIZE;
	offset = 0;
	while (to_read > 0) {
		gssize len = recv(sock->fd, header + offset, to_read, 0);
		if (len == -1 || len == 0) {
			network_socket_free(sock);
			g_string_free(data, TRUE);
			network_mysqld_auth_challenge_free(challenge);
			return NULL;
		}
		offset += len;
		to_read -= len;
	}

	to_read = header[0] + (header[1] << 8) + (header[2] << 16);
	offset = 0;
	g_string_truncate(data, 0);
	g_string_set_size(data, to_read);
	while (to_read > 0) {
		gssize len = recv(sock->fd, data->str + offset, to_read, 0);
		if (len == -1 || len == 0) {
			network_socket_free(sock);
			g_string_free(data, TRUE);
			network_mysqld_auth_challenge_free(challenge);
			return NULL;
		}
		offset += len;
		to_read -= len;
	}
	data->len = offset;

	if (data->str[0] != MYSQLD_PACKET_OK) {
		network_socket_free(sock);
		g_string_free(data, TRUE);
		network_mysqld_auth_challenge_free(challenge);
		return NULL;
	}
	g_string_free(data, TRUE);

	//6. set non-block
	network_socket_set_non_blocking(sock);
	network_socket_connect_setopts(sock);	//此句是否需要?是否应该放在第1步末尾?

	sock->challenge = challenge;
	sock->response = network_mysqld_auth_response_copy(con->client->response);
    g_atomic_int_inc(&backend->connected_clients);
	return sock;
}
/**
 * 测试zabbix没有启动的情况
 * @return
 */
void test_admin_backend_mange_Add(void) {
	/** 初始化内存变量*/
	network_backend_t *b = NULL;
	chassis *srv1 = g_new0(chassis, 1);
	srv1->priv = g_new0(chassis_private, 1);
	srv1->priv->backends  = network_backends_new();
	srv1->xml_filename = "test_config.xml";
	network_backends_add(srv1->priv->backends, "X.X.X.X:3306#2#UP", BACKEND_TYPE_RW);
	b = network_backends_get(srv1->priv->backends, 0);
	g_mutex_init(&(b->mutex[0]));
	g_mutex_init(&(b->mutex[1]));

	network_backends_add(srv1->priv->backends, "X.X.X.X:3306#3#UP", BACKEND_TYPE_RO);
	b = network_backends_get(srv1->priv->backends, 1);
	g_mutex_init(&(b->mutex[0]));
	g_mutex_init(&(b->mutex[1]));

	network_mysqld_con *con = network_mysqld_con_new();
	con->client = network_socket_new();
	con->srv = srv1;
	con->srv->detect_threads = g_ptr_array_new();
	//network_mysqld_add_connection(srv1, con);

	gchar *cmd = g_strdup("addBackend --backend=X.X.X.X:3306");
	g_assert_cmpint(COMMAND_PROCESS_ERROR, ==, admin_command_process(con, cmd));
	g_free(cmd);
	cmd = NULL;

	cmd = g_strdup("addBackend");
        g_assert_cmpint(COMMAND_PROCESS_ERROR, ==, admin_command_process(con, cmd));
        g_free(cmd);
        cmd = NULL;

	g_assert(COMMAND_NO_QUERY_SPECIFIED == admin_command_process(con, NULL));

	cmd = g_strdup("addBackend --backend=X.X.X.X:3307");
	g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd));
	g_free(cmd);
	cmd = NULL;

	cmd = g_strdup("addBackend --backend=X.X.X.X:3307#1#up --bktype=rw");
        g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd));
        g_free(cmd);
        cmd = NULL;

	cmd = g_strdup("addBackend --backend=X.X.X.X:3307 --bktype=ro");
        g_assert(COMMAND_PROCESS_SUCCESS == admin_command_process(con, cmd));
	network_backend_t *backend = network_backends_get_by_name(srv1->priv->backends, "X.X.X.X:3307");
	g_assert(backend);
	g_free(cmd);
	cmd = NULL;

	cmd = g_strdup("addBackend --backend=192.1968.x.xx:3308");
	g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd));
	g_free(cmd);
	cmd = NULL;

	cmd = g_strdup("addBackend --backends=X.X.X.X:3308");
	g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd));
	g_free(cmd);
	cmd = NULL;

	cmd = g_strdup("addBackend --backend=X.X.X.X:103307");
	g_assert(COMMAND_PROCESS_ERROR == admin_command_process(con, cmd));
	g_free(cmd);
	cmd = NULL;

	cmd = g_strdup("addBackends --backend=X.X.X.X:3308");
	g_assert(COMMAND_NOT_SUPPORT == admin_command_process(con, cmd));
	g_free(cmd);
	cmd = NULL;

//	g_ptr_array_free(con->srv->detect_threads, TRUE);
//	con->srv->detect_threads = NULL;

	//network_mysqld_con_free(con);
	//con = NULL;

	//network_backends_free(srv1->priv->backends);
	//srv1->priv->backends = NULL;

	//g_free(srv1->priv);
	//srv1->priv = NULL;

	//g_free(srv1);
	//srv1 = NULL;
}