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
static network_socket_retval_t network_socket_connect_setopts(network_socket *sock) {
	int val = 1;
	/**
	 * set the same options as the mysql client 
	 */
#ifdef IP_TOS
	val = 8;
	setsockopt(sock->fd, IPPROTO_IP,     IP_TOS, &val, sizeof(val));
#endif
	val = 1;
	setsockopt(sock->fd, IPPROTO_TCP,    TCP_NODELAY, &val, sizeof(val) );
	val = 1;
	setsockopt(sock->fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val) );

	/* the listening side may be INADDR_ANY, let's get which address the client really connected to */
	if (-1 == getsockname(sock->fd, &sock->src->addr.common, &(sock->src->len))) {
		g_debug("%s: getsockname() failed: %s (%d)",
				G_STRLOC,
				g_strerror(errno),
				errno);
		network_address_reset(sock->src);
	} else if (network_address_refresh_name(sock->src)) {
		g_debug("%s: network_address_refresh_name() failed",
				G_STRLOC);
		network_address_reset(sock->src);
	}

	return NETWORK_SOCKET_SUCCESS;
}
Esempio n. 3
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. 4
0
static gint network_address_set_address_un(network_address *addr, const gchar *address) {
	g_return_val_if_fail(addr, -1);
	g_return_val_if_fail(address, -1);

#ifdef HAVE_SYS_UN_H
	if (strlen(address) >= sizeof(addr->addr.un.sun_path) - 1) {
		g_critical("unix-path is too long: %s", address);
		return -1;
	}

	addr->addr.un.sun_family = AF_UNIX;
	strcpy(addr->addr.un.sun_path, address);
	addr->len = sizeof(struct sockaddr_un);
	
	network_address_refresh_name(addr);

	return 0;
#else
	return -1;
#endif
}
Esempio n. 5
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. 6
0
static gint network_address_set_address_ip(network_address *addr, const gchar *address, guint port) {
	g_return_val_if_fail(addr, -1);

	if (port > 65535) {
		g_critical("%s: illegal value %u for port, only 1 ... 65535 allowed",
				G_STRLOC, port);
		return -1;
	}

	memset(&addr->addr.ipv4, 0, sizeof(struct sockaddr_in));

	if (NULL == address ||
	    strlen(address) == 0 || 
	    0 == strcmp("0.0.0.0", address)) {
		/* no ip */
		addr->addr.ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
		addr->addr.ipv4.sin_family = AF_INET; /* "default" family */
	} else {
#ifdef HAVE_GETADDRINFO
		struct addrinfo *ai = NULL, hint;
		int				rc, family;
		
		memset(&hint, 0, sizeof (hint));
		/*
		 * FIXME: when we add support for IPv6, we'll have to do one
		 * PF_INET* after the other
		 */
		hint.ai_family = PF_INET;
		if ((rc = getaddrinfo(address, NULL, &hint, &ai)) != 0) {
			g_critical("getaddrinfo(%s) failed with %s", address, 
					   gai_strerror(rc));
			return -1;
		}

		do {
			family = ai->ai_family;
#if 0 /* keep this for when we do IPv6 */
			if (family == PF_INET6) {
				memcpy(&addr->addr.ipv6,
						(struct sockaddr_in6 *) ai->ai_addr,
						sizeof (addr->addr.ipv6));
				break;
			} 
#endif /* 0 */
			if (family == PF_INET) {
				memcpy(&addr->addr.ipv4,
						(struct sockaddr_in *) ai->ai_addr, 
						sizeof (addr->addr.ipv4));
				break;
			}
			ai = ai->ai_next;
		} while (NULL != ai);

		if (ai == NULL) {
			/* the family we print here is the *last* ai's */
			g_critical("address %s doesn't resolve to a valid/supported "
					   "address family: %d expected, last found %d", address,
					   PF_INET, family);
			freeaddrinfo(ai);
			return -1;
		}

		freeaddrinfo(ai);
#else 
		struct hostent	*he;
		static GStaticMutex gh_mutex = G_STATIC_MUTEX_INIT;

		g_static_mutex_lock(&gh_mutex);

		he = gethostbyname(address);
		if (NULL == he) {
			g_static_mutex_unlock(&gh_mutex);
			return -1;
		}

		g_assert(he->h_addrtype == AF_INET);
		g_assert(he->h_length == sizeof(struct in_addr));

		memcpy(&(addr->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
		g_static_mutex_unlock(&gh_mutex);
		addr->addr.ipv4.sin_family = AF_INET;
#endif /* HAVE_GETADDRINFO */
	}

	addr->addr.ipv4.sin_port = htons(port);
	addr->len = sizeof(struct sockaddr_in);

	(void) network_address_refresh_name(addr);

	return 0;
}