Esempio n. 1
0
network_socket *network_socket_new() {
	network_socket *s;
	
	s = g_new0(network_socket, 1);

	s->send_queue = network_queue_new();
	s->recv_queue = network_queue_new();
	s->recv_queue_raw = network_queue_new();

    s->default_db = g_string_new(NULL);
    s->charset = g_string_new(NULL);
    s->charset_client = g_string_new(NULL);
    s->charset_connection = g_string_new(NULL);
    s->charset_results = g_string_new(NULL);
    s->sql_mode = g_string_new(NULL);

	s->fd           = -1;
	s->socket_type  = SOCK_STREAM; /* let's default to TCP */
	s->packet_id_is_reset = TRUE;

	s->src = network_address_new();
	s->dst = network_address_new();
    s->last_visit_time = time(0);

	return s;
}
Esempio n. 2
0
void t_network_address_new() {
    network_address *addr;

    addr = network_address_new();

    network_address_free(addr);
}
Esempio n. 3
0
void t_network_address_set() {
	network_address *addr;

	addr = network_address_new();

	g_assert_cmpint(network_address_set_address(addr, "127.0.0.1:3306"), ==, 0);
	g_assert_cmpint(network_address_set_address(addr, "127.0.0.1"), ==, 0);

	g_log_set_always_fatal(G_LOG_FATAL_MASK);
	/* shouldn't crash.
	 *
	 * we can't test if it works as we can't know if the host has setup IPv6
	 */
	network_address_set_address(addr, "[::1]");
	network_address_set_address(addr, "[::1]:3306");

	/* should fail */	
	g_assert_cmpint(network_address_set_address(addr, "500.0.0.1"), ==, -1);
	g_assert_cmpint(network_address_set_address(addr, "127.0.0.1:"), ==, -1);
	g_assert_cmpint(network_address_set_address(addr, "[::1]:"), ==, -1);
	g_assert_cmpint(network_address_set_address(addr, "127.0.0.1:65536"), ==, -1);
	g_assert_cmpint(network_address_set_address(addr, "127.0.0.1:-1"), ==, -1);

	network_address_free(addr);
}
Esempio n. 4
0
static void
t_network_address_tostring_unix() {
#ifndef _WIN32
	network_address *addr;
	char buf[255];
	gsize buf_len = sizeof(buf);
	GError *gerr = NULL;

	addr = network_address_new();

	g_assert_cmpint(network_address_set_address(addr, "/foobar"), ==, 0);

	buf_len = sizeof(buf); /* should be large enough */
	g_assert_cmpstr(network_address_tostring(addr, buf, &buf_len, NULL), ==, "/foobar");
	g_assert_cmpint(7 + 1, ==, buf_len);

	buf_len = 3; /* too small */
	g_assert(NULL == network_address_tostring(addr, buf, &buf_len, &gerr));
	g_assert_cmpint(NETWORK_ADDRESS_ERROR, ==, gerr->domain);
	g_assert_cmpint(NETWORK_ADDRESS_ERROR_DST_TOO_SMALL, ==, gerr->code);
	g_clear_error(&gerr);

	network_address_free(addr);
#endif
}
Esempio n. 5
0
static void
t_network_address_tostring_ipv6() {
#ifdef AF_INET6
	network_address *addr;
	char buf[255];
	gsize buf_len = sizeof(buf);
	GError *gerr = NULL;

	addr = network_address_new();

	if (0 != network_address_set_address(addr, "[::1]")) {
		/* skip test, if resolving ::1 fails */
		network_address_free(addr);
		return;
	}

	buf_len = sizeof(buf); /* should be large enough */
	g_assert_cmpstr(network_address_tostring(addr, buf, &buf_len, NULL), ==, "::1");
	g_assert_cmpint(3 + 1, ==, buf_len);

	buf_len = 3; /* too small */
	g_assert(NULL == network_address_tostring(addr, buf, &buf_len, &gerr));
	g_assert_cmpint(NETWORK_ADDRESS_ERROR, ==, gerr->domain);
	g_assert_cmpint(NETWORK_ADDRESS_ERROR_DST_TOO_SMALL, ==, gerr->code);
	g_clear_error(&gerr);

	network_address_free(addr);
#endif
}
Esempio n. 6
0
network_address *network_address_copy(network_address *dst, network_address *src) {
	if (!dst) dst = network_address_new();

	dst->len = src->len;
	dst->addr = src->addr;
	g_string_assign_len(dst->name, S(src->name));

	return dst;
}
network_backend_t *network_backend_new() {
	network_backend_t *b;

	b = g_new0(network_backend_t, 1);

	b->pool = network_connection_pool_new();
	b->uuid = g_string_new(NULL);
	b->addr = network_address_new();

	return b;
}
Esempio n. 8
0
network_backend_t *network_backend_new(guint event_thread_count) {
	network_backend_t *b = g_new0(network_backend_t, 1);

	b->pools = g_ptr_array_new();
	guint i;
	for (i = 0; i <= event_thread_count; ++i) {
		network_connection_pool* pool = network_connection_pool_new();
		g_ptr_array_add(b->pools, pool);
	}

	b->uuid = g_string_new(NULL);
	b->addr = network_address_new();

	return b;
}
Esempio n. 9
0
void t_network_address_set() {
    network_address *addr;

    addr = network_address_new();

    g_assert_cmpint(network_address_set_address(addr, "127.0.0.1:3306"), ==, 0);
    g_assert_cmpint(network_address_set_address(addr, "127.0.0.1"), ==, 0);

    g_log_set_always_fatal(G_LOG_FATAL_MASK);

    /* should fail */
    g_assert_cmpint(network_address_set_address(addr, "500.0.0.1"), ==, -1);
    g_assert_cmpint(network_address_set_address(addr, "127.0.0.1:"), ==, -1);
    g_assert_cmpint(network_address_set_address(addr, "127.0.0.1:65536"), ==, -1);
    g_assert_cmpint(network_address_set_address(addr, "127.0.0.1:-1"), ==, -1);

    network_address_free(addr);
}
Esempio n. 10
0
/**
 * test if we decode the port number correctly
 */
void t_network_address_resolve() {
    network_address *addr;

    g_test_bug("43313");

    addr = network_address_new();
    network_address_set_address(addr, "127.0.0.1:3306");

    /* _set_address() should set the port number */
    g_assert_cmpint(ntohs(addr->addr.ipv4.sin_port), ==, 3306);

    /* reset the name to see that _refresh_name() updates to the right value */
    g_string_truncate(addr->name, 0);

    network_address_refresh_name(addr);

    g_assert_cmpstr(addr->name->str, ==, "127.0.0.1:3306");

    network_address_free(addr);
}
Esempio n. 11
0
/**
 * test if we convert addr->string correctly for IPv6
 */
void t_network_address_resolve_ipv6() {
	network_address *addr;

	addr = network_address_new();
	if (0 != network_address_set_address(addr, "[::1]")) {
		/* skip test, if resolving ::1 fails */
		network_address_free(addr);

		return;
	}

	/* _set_address() should set the port number */

	/* reset the name to see that _refresh_name() updates to the right value */
	g_string_truncate(addr->name, 0);

	network_address_refresh_name(addr);

	g_assert_cmpstr(addr->name->str, ==, "[::1]:3306");

	network_address_free(addr);
}
Esempio n. 12
0
/**
 * connect a socket
 *
 * the con->dst->addr has to be set before 
 * 
 * @param con    a socket 
 * @return       NETWORK_SOCKET_SUCCESS on connected, NETWORK_SOCKET_ERROR on error
 *
 * @see network_address_set_address()
 */
network_socket_retval_t network_socket_bind(network_socket * con) {
	/* 
	 * HPUX:       int setsockopt(int s,    int level, int optname, const void *optval, int optlen);
	 * all others: int setsockopt(int s,    int level, int optname, const void *optval, socklen_t optlen);
	 */
#define SETSOCKOPT_OPTVAL_CAST (void *)

	g_return_val_if_fail(con->fd < 0, NETWORK_SOCKET_ERROR); /* socket is already bound */
	g_return_val_if_fail((con->socket_type == SOCK_DGRAM) || (con->socket_type == SOCK_STREAM), NETWORK_SOCKET_ERROR);

	if (con->socket_type == SOCK_STREAM) {
		g_return_val_if_fail(con->dst, NETWORK_SOCKET_ERROR);
		g_return_val_if_fail(con->dst->name->len > 0, NETWORK_SOCKET_ERROR);

		if (-1 == (con->fd = socket(con->dst->addr.common.sa_family, con->socket_type, 0))) {
			g_critical("%s: socket(%s) failed: %s (%d)", 
					G_STRLOC,
					con->dst->name->str,
					g_strerror(errno), errno);
			return NETWORK_SOCKET_ERROR;
		}

		if (con->dst->addr.common.sa_family == AF_INET || 
		    con->dst->addr.common.sa_family == AF_INET6) {
			/* TCP_NODELAY  is int on unix */
			/* SO_REUSEADDR is int on unix */
			int val;

			val = 1;
			if (0 != setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, SETSOCKOPT_OPTVAL_CAST &val, sizeof(val))) {
				g_critical("%s: setsockopt(%s, IPPROTO_TCP, TCP_NODELAY) failed: %s (%d)", 
						G_STRLOC,
						con->dst->name->str,
						g_strerror(errno), errno);
				return NETWORK_SOCKET_ERROR;
			}
		
			if (0 != setsockopt(con->fd, SOL_SOCKET, SO_REUSEADDR, SETSOCKOPT_OPTVAL_CAST &val, sizeof(val))) {
				g_critical("%s: setsockopt(%s, SOL_SOCKET, SO_REUSEADDR) failed: %s (%d)", 
						G_STRLOC,
						con->dst->name->str,
						g_strerror(errno), errno);
				return NETWORK_SOCKET_ERROR;
			}
		}

		if (con->dst->addr.common.sa_family == AF_INET6) {
#ifdef IPV6_V6ONLY
			/* disable dual-stack IPv4-over-IPv6 sockets
			 *
			 * ... if it is supported:
			 * - Linux
			 * - Mac OS X
			 * - FreeBSD
			 * - Solaris 10 and later
			 *
			 * no supported on:
			 * - Solaris 9 and earlier
			 */

			/* IPV6_V6ONLY is int on unix */
			int val;

			val = 0;
			if (0 != setsockopt(con->fd, IPPROTO_IPV6, IPV6_V6ONLY, SETSOCKOPT_OPTVAL_CAST &val, sizeof(val))) {
				g_critical("%s: setsockopt(%s, IPPROTO_IPV6, IPV6_V6ONLY) failed: %s (%d)", 
						G_STRLOC,
						con->dst->name->str,
						g_strerror(errno), errno);
				return NETWORK_SOCKET_ERROR;
			}
#endif
		}

		if (-1 == bind(con->fd, &con->dst->addr.common, con->dst->len)) {
			gchar *address_copy;

			/* binding failed so the address/socket is already being used
			 * let's check if we can connect to it so we check if is being used 
			 * by some app
			 */
			if (-1 == connect(con->fd, &con->dst->addr.common, con->dst->len)) {
				g_debug("%s.%d: connect(%s) failed: %s (%d)", 
					__FILE__, __LINE__,
					con->dst->name->str,
					g_strerror(errno), errno);
				/* we can't connect to the socket so no one is listening on it. We need
				 * to unlink it (delete the name from the file system) to be able to
				 * re-use it.
				 * network_address_free does the unlink, but to re-use it we need
				 * to store the pathname associated with the socket before unlink it and
				 * create a new socket with it.
				 */
				address_copy = g_strdup(con->dst->name->str);
				con->dst->can_unlink_socket = TRUE;
				network_address_free(con->dst);

				con->dst = network_address_new();
				network_address_set_address(con->dst, address_copy);

				/* we can now free the address copy */
				g_free(address_copy);

				g_debug("%s: retrying to bind(%s)",
						G_STRLOC,
						con->dst->name->str);

				/* let's bind again with the new socket */
				if (-1 == bind(con->fd, &con->dst->addr.common, con->dst->len)) {
					g_critical("%s: bind(%s) failed: %s (%d)", 
						G_STRLOC,
						con->dst->name->str,
						g_strerror(errno), errno);

					return NETWORK_SOCKET_ERROR;
				}
			} else {
				g_critical("%s: bind(%s) failed: %s (%d)", 
					G_STRLOC,
					con->dst->name->str,
					g_strerror(errno), errno);

				return NETWORK_SOCKET_ERROR;	
			}
		}

		if (con->dst->addr.common.sa_family == AF_INET &&
		    con->dst->addr.ipv4.sin_port == 0) {
			struct sockaddr_in a;
			socklen_t          a_len = sizeof(a);

			if (0 != getsockname(con->fd, (struct sockaddr *)&a, &a_len)) {
				g_critical("%s: getsockname(%s) failed: %s (%d)", 
						G_STRLOC,
						con->dst->name->str,
						g_strerror(errno), errno);
				return NETWORK_SOCKET_ERROR;
			}
			con->dst->addr.ipv4.sin_port  = a.sin_port;
		} else if (con->dst->addr.common.sa_family == AF_INET6 &&
		           con->dst->addr.ipv6.sin6_port == 0) {
			struct sockaddr_in6 a;
			socklen_t          a_len = sizeof(a);

			if (0 != getsockname(con->fd, (struct sockaddr *)&a, &a_len)) {
				g_critical("%s: getsockname(%s) failed: %s (%d)", 
						G_STRLOC,
						con->dst->name->str,
						g_strerror(errno), errno);
				return NETWORK_SOCKET_ERROR;
			}
			con->dst->addr.ipv6.sin6_port  = a.sin6_port;
		}

		if (-1 == listen(con->fd, 128)) {
			g_critical("%s: listen(%s, 128) failed: %s (%d)",
					G_STRLOC,
					con->dst->name->str,
					g_strerror(errno), errno);
			return NETWORK_SOCKET_ERROR;
		}
	} else {
		/* UDP sockets bind the ->src address */
		g_return_val_if_fail(con->src, NETWORK_SOCKET_ERROR);
		g_return_val_if_fail(con->src->name->len > 0, NETWORK_SOCKET_ERROR);

		if (-1 == (con->fd = socket(con->src->addr.common.sa_family, con->socket_type, 0))) {
			g_critical("%s: socket(%s) failed: %s (%d)", 
					G_STRLOC,
					con->src->name->str,
					g_strerror(errno), errno);
			return NETWORK_SOCKET_ERROR;
		}

		if (-1 == bind(con->fd, &con->src->addr.common, con->src->len)) {
			g_critical("%s: bind(%s) failed: %s (%d)", 
					G_STRLOC,
					con->src->name->str,
					g_strerror(errno), errno);
			return NETWORK_SOCKET_ERROR;
		}
	}

	con->dst->can_unlink_socket = TRUE;
	return NETWORK_SOCKET_SUCCESS;
}
Esempio n. 13
0
static
gint
admin_reload_backends(
    network_mysqld_con*			con,
    GPtrArray*					backend_addr_str_array,
    gint						fail_flag
)
{
    chassis*					srv;
    network_backends_t*			backends;
    GPtrArray*					cons;
    gchar*						s;
    gchar*						new_backend_addr;
    guint						i;
    //gchar						ip_address[MAX_IP_PORT_STRING_LEN + 1];
    admin_network_addr_t*		addr;
    GPtrArray*					addr_array;
    gint						ret = EC_ADMIN_RELOAD_SUCCESS;
    gboolean					all_same_flag = 1;
    guint						server_cnt = 0;
    guint						client_cnt = 0;

    srv			= con->srv;
    backends	= srv->priv->backends;
    cons		= srv->priv->cons;

    //for test
    if (fail_flag == 1000)
    {
        admin_print_all_backend_cons(con->srv);
        return EC_ADMIN_RELOAD_SUCCESS;
    }

    if (backend_addr_str_array->len != backends->backends->len)
    {
        g_critical("%s: Number of refresh backends num is not matched, new backends :%d, orignal backends : %d",
                   G_STRLOC, backend_addr_str_array->len , backends->backends->len);
        return EC_ADMIN_RELOAD_FAIL;
    }

    if (fail_flag != 0 && fail_flag != 1)
    {
        g_critical("%s: Fail flag of refresh backends must be 0 or 1, but the flag is %d",
                   G_STRLOC, fail_flag);
        return EC_ADMIN_RELOAD_FAIL;
    }

    addr_array	= g_ptr_array_new();

    /* 1. 测试DR连通性 */
    for (i = 0; i < backend_addr_str_array->len; ++i)
    {
        new_backend_addr = g_ptr_array_index(backend_addr_str_array, i);
        addr			 = g_new0(admin_network_addr_t, 1);
        g_ptr_array_add(addr_array, addr);

        s = strchr(new_backend_addr, ':');

        if (NULL != s)
        {
            gint				len;
            char *				port_err = NULL;
            network_backend_t*	backend;

            backend = g_ptr_array_index(backends->backends, i);

            //check whether all backends are same
            //to do check backend:127.0.0.1:3306, addr:ip:3306?
            if (all_same_flag && g_strcasecmp(new_backend_addr, backend->addr->name->str) != 0 ||
                    backend->state == BACKEND_STATE_DOWN)
            {
                all_same_flag = 0;
            }


            len = s - new_backend_addr;
            if (len <=  MAX_IP_PORT_STRING_LEN)
            {
                memcpy(addr->ip_address, new_backend_addr, len);
                addr->ip_address[len] = '\0';

                addr->port = strtoul(s + 1, &port_err, 10);
            }

            if (len > MAX_IP_PORT_STRING_LEN ||
                    *(s + 1) == '\0')
            {
                g_critical("%s: Reload IP-address has to be in the form [<ip>][:<port>], is '%s'. No port number",
                           G_STRLOC, new_backend_addr);
                ret = EC_ADMIN_RELOAD_FAIL;
            }
            else if (*port_err != '\0')
            {
                g_critical("%s: Reload IP-address has to be in the form [<ip>][:<port>], is '%s'. Failed to parse the port at '%s'",
                           G_STRLOC, new_backend_addr, port_err);
                ret = EC_ADMIN_RELOAD_FAIL;
            }
            else
            {
                addr->addr = network_address_new();
                if (network_address_set_address_ip(addr->addr, addr->ip_address, addr->port))
                {
                    g_critical("%s: Reload IP-address %s : %d error",
                               G_STRLOC, addr->ip_address, addr->port);
                    ret = EC_ADMIN_RELOAD_FAIL;
                }
                //ping the ip address and port;
                //ret = network_address_set_address_ip(addr, ip_address, port);
                //to do
            }
        }
        else
            ret = EC_ADMIN_RELOAD_FAIL;

        if (EC_ADMIN_RELOAD_FAIL == ret)
        {
            g_ptr_array_free_all(addr_array, admin_network_addr_free);
            return ret;
        }
    }

    //backends are same
    if (all_same_flag)
    {
        g_ptr_array_free_all(addr_array, admin_network_addr_free);
        return EC_ADMIN_RELOAD_SUCCESS;
    }

    /* 2. 置当前所有backends为down */
    g_mutex_lock(backends->backends_mutex);
    for (i = 0; i < backends->backends->len; ++i)
    {
        network_backend_t*		backend;

        backend = g_ptr_array_index(backends->backends, i);

        backend->state = BACKEND_STATE_DOWN;
    }
    g_mutex_unlock(backends->backends_mutex);

    /* 3. 当前backend为新地址 */
    g_mutex_lock(backends->backends_mutex);
    for (i = 0; i < backends->backends->len; ++i)
    {
        network_backend_t*		backend;

        backend = g_ptr_array_index(backends->backends, i);

        addr = g_ptr_array_index(addr_array, i);

        network_address_copy(backend->addr, addr->addr);

// 		backend->addr->name->len = 0; /* network refresh name */
//
// 		if (network_address_set_address_ip(backend->addr, addr->ip_address, addr->port))
// 		{
// 			g_critical("%s: Reload IP-address %s : %d error"
// 				G_STRLOC, addr->ip_address, addr->port);
// 			ret = EC_ADMIN_RELOAD_FAIL;
//
// 			break;
// 		}
    }
    g_mutex_unlock(backends->backends_mutex);


    /* 4. 关闭proxy当前所有连接 */
    g_mutex_lock(srv->priv->cons_mutex);
    for (i = 0; i < cons->len; ++i)
    {
        con = g_ptr_array_index(cons, i);

        //区分了是否为backends的连接
        if (con->server && con->server->backend_idx != -1)
        {
            //g_assert(con->server->fd != -1);
            if (con->server->fd != -1)
            {
                //closesocket(con->server->fd);
                con->server->fd_bak	= con->server->fd; /* 后端连接暂不关闭,让其正常处理正在进行的事件 */
                con->server->fd		= -1;
                con->server->disconnect_flag = 1;
                server_cnt++;
            }

            //g_assert(con->client && con->client->fd != -1);
            if (con->client && con->client->fd != -1)
            {
// 				int c_fd = con->client->fd;
// 				con->client->fd		= -1;
// 				closesocket(c_fd);						/* 需主动关闭前端fd,防止前端一直等待,但会导致con资源没有释放 */
                client_cnt++;
            }

            /* 以上操作可能产生一种情况:客户端请求已在DB执行成功,但前端认为连接已断开 */

            switch(con->state)
            {
            case CON_STATE_CLOSE_CLIENT:
            case CON_STATE_CLOSE_SERVER:
            case CON_STATE_SEND_ERROR:
            case CON_STATE_ERROR:
                break;

            case CON_STATE_INIT:
            case CON_STATE_CONNECT_SERVER:
            case CON_STATE_READ_HANDSHAKE:
            case CON_STATE_SEND_HANDSHAKE:
            case CON_STATE_READ_AUTH:
            case CON_STATE_SEND_AUTH:
            case CON_STATE_READ_AUTH_RESULT:
            case CON_STATE_SEND_AUTH_RESULT:
            case CON_STATE_READ_AUTH_OLD_PASSWORD:
            case CON_STATE_SEND_AUTH_OLD_PASSWORD:
                break;

            case CON_STATE_READ_QUERY:
            case CON_STATE_SEND_QUERY:
                break;

            case CON_STATE_READ_QUERY_RESULT:
            case CON_STATE_SEND_QUERY_RESULT:
// 				//需要主动关闭连接
// 				if (fail_flag == 1)
// 				{
// 					if (con->client->fd != -1)
// 					{
// 						closesocket(con->client->fd);
// 						con->client->fd = -1;
// 					}
// 				}
                break;

            case CON_STATE_READ_LOCAL_INFILE_DATA:
            case CON_STATE_SEND_LOCAL_INFILE_DATA:
            case CON_STATE_READ_LOCAL_INFILE_RESULT:
            case CON_STATE_SEND_LOCAL_INFILE_RESULT:
                break;
            }

        }
    }
    g_message("%s reload backends: connection count %d, close server count %d, close client count %d",
              G_STRLOC, srv->priv->cons->len, server_cnt, client_cnt);
    g_mutex_unlock(srv->priv->cons_mutex);

    if (ret != EC_ADMIN_RELOAD_SUCCESS)
        goto destroy_end;

    /* 5. 再把后端状态置为unknown,接收新连接 */
    g_mutex_lock(backends->backends_mutex);
    for (i = 0; i < backends->backends->len; ++i)
    {
        network_backend_t*		backend;

        backend = g_ptr_array_index(backends->backends, i);

        backend->state = BACKEND_STATE_UNKNOWN;
    }
    g_mutex_unlock(backends->backends_mutex);

    /* 6. 刷新配置 */
    ret = admin_configure_flush_to_file(srv);

destroy_end:
    g_ptr_array_free_all(addr_array, admin_network_addr_free);
    return ret;
}