Пример #1
0
/* Connect to server, call func when finished */
int net_connect_nonblock(const char *server, int port, const IPADDR *my_ip,
                         NET_CALLBACK func, void *data)
{
    SIMPLE_THREAD_REC *rec;
    int fd[2];

    g_return_val_if_fail(server != NULL, FALSE);
    g_return_val_if_fail(func != NULL, FALSE);

    if (pipe(fd) != 0) {
        g_warning("net_connect_nonblock(): pipe() failed.");
        return FALSE;
    }

    rec = g_new0(SIMPLE_THREAD_REC, 1);
    rec->port = port;
    if (my_ip != NULL) {
        rec->my_ip = g_malloc(sizeof(IPADDR));
        memcpy(rec->my_ip, my_ip, sizeof(IPADDR));
    }
    rec->func = func;
    rec->data = data;
    rec->pipes[0] = g_io_channel_new(fd[0]);
    rec->pipes[1] = g_io_channel_new(fd[1]);

    /* start nonblocking host name lookup */
    net_gethostbyname_nonblock(server, rec->pipes[1], 0);
    rec->tag = g_input_add(rec->pipes[0], G_INPUT_READ,
                           (GInputFunction) simple_readpipe, rec);

    return TRUE;
}
Пример #2
0
/* starts connecting to server */
int server_start_connect(SERVER_REC *server)
{
	const char *connect_address;
        int fd[2];

	g_return_val_if_fail(server != NULL, FALSE);
	if (!server->connrec->unix_socket && server->connrec->port <= 0)
		return FALSE;

	server->rawlog = rawlog_create();

	if (server->connrec->connect_handle != NULL) {
		/* already connected */
		GIOChannel *handle = server->connrec->connect_handle;

		server->connrec->connect_handle = NULL;
		server->handle = net_sendbuffer_create(handle, 0);
		server_connect_finished(server);
	} else if (server->connrec->unix_socket) {
		/* connect with unix socket */
		server_real_connect(server, NULL, server->connrec->address);
	} else {
		/* resolve host name */
		if (pipe(fd) != 0) {
			g_warning("server_connect(): pipe() failed.");
			g_free(server->tag);
			g_free(server->nick);
			return FALSE;
		}

		server->connect_pipe[0] = g_io_channel_new(fd[0]);
		server->connect_pipe[1] = g_io_channel_new(fd[1]);

		connect_address = server->connrec->proxy != NULL ?
			server->connrec->proxy : server->connrec->address;
		server->connect_pid =
			net_gethostbyname_nonblock(connect_address,
						   server->connect_pipe[1],
						   settings_get_bool("resolve_reverse_lookup"));
		server->connect_tag =
			g_input_add(server->connect_pipe[0], G_INPUT_READ,
				    (GInputFunction)
				    server_connect_callback_readpipe,
				    server);

		lookup_servers = g_slist_append(lookup_servers, server);

		signal_emit("server looking", 1, server);
	}
	return TRUE;
}
Пример #3
0
/* Connect to named UNIX socket */
GIOChannel *net_connect_unix(const char *path)
{
	struct sockaddr_un sa;
	int handle, ret;

	/* create the socket */
	handle = socket(PF_UNIX, SOCK_STREAM, 0);
	if (handle == -1)
		return NULL;

	/* set socket options */
#ifndef WIN32
	fcntl(handle, F_SETFL, O_NONBLOCK);
#endif

	/* connect */
	memset(&sa, 0, sizeof(sa));
	sa.sun_family = AF_UNIX;
	strncpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
	sa.sun_path[sizeof(sa.sun_path)-1] = '\0';

	ret = connect(handle, (struct sockaddr *) &sa, sizeof(sa));
	if (ret < 0 && errno != EINPROGRESS) {
		int old_errno = errno;
		close(handle);
		errno = old_errno;
		return NULL;
	}

	return g_io_channel_new(handle);
}
Пример #4
0
/* Connect to socket with ip address */
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
{
	union sockaddr_union so;
	int handle, ret, opt = 1;

	if (my_ip != NULL && ip->family != my_ip->family) {
		g_warning("net_connect_ip(): ip->family != my_ip->family");
                my_ip = NULL;
	}

	/* create the socket */
	memset(&so, 0, sizeof(so));
        so.sin.sin_family = ip->family;
	handle = socket(ip->family, SOCK_STREAM, 0);

	if (handle == -1)
		return NULL;

	/* set socket options */
#ifndef WIN32
	fcntl(handle, F_SETFL, O_NONBLOCK);
#endif
	setsockopt(handle, SOL_SOCKET, SO_REUSEADDR,
		   (char *) &opt, sizeof(opt));
	setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE,
		   (char *) &opt, sizeof(opt));

	/* set our own address */
	if (my_ip != NULL) {
		sin_set_ip(&so, my_ip);
		if (bind(handle, &so.sa, SIZEOF_SOCKADDR(so)) == -1) {
			/* failed, set it back to INADDR_ANY */
			sin_set_ip(&so, NULL);
			bind(handle, &so.sa, SIZEOF_SOCKADDR(so));
		}
	}

	/* connect */
	sin_set_ip(&so, ip);
	sin_set_port(&so, port);
	ret = connect(handle, &so.sa, SIZEOF_SOCKADDR(so));

#ifndef WIN32
	if (ret < 0 && errno != EINPROGRESS)
#else
	if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
#endif
	{
		int old_errno = errno;
		close(handle);
		errno = old_errno;
		return NULL;
	}

	return g_io_channel_new(handle);
}
Пример #5
0
/* Listen for connections on a socket. if `my_ip' is NULL, listen in any
   address. */
GIOChannel *net_listen(IPADDR *my_ip, int *port)
{
	union sockaddr_union so;
	int ret, handle, opt = 1;
	socklen_t len;

	g_return_val_if_fail(port != NULL, NULL);

	memset(&so, 0, sizeof(so));
	sin_set_port(&so, *port);
	sin_set_ip(&so, my_ip);

	/* create the socket */
	handle = socket(so.sin.sin_family, SOCK_STREAM, 0);
#ifdef HAVE_IPV6
	if (handle == -1 && (errno == EINVAL || errno == EAFNOSUPPORT)) {
		/* IPv6 is not supported by OS */
		so.sin.sin_family = AF_INET;
		so.sin.sin_addr.s_addr = INADDR_ANY;

		handle = socket(AF_INET, SOCK_STREAM, 0);
	}
#endif
	if (handle == -1)
		return NULL;

	/* set socket options */
#ifndef WIN32
	fcntl(handle, F_SETFL, O_NONBLOCK);
#endif
	setsockopt(handle, SOL_SOCKET, SO_REUSEADDR,
		   (char *) &opt, sizeof(opt));
	setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE,
		   (char *) &opt, sizeof(opt));

	/* specify the address/port we want to listen in */
	ret = bind(handle, &so.sa, SIZEOF_SOCKADDR(so));
	if (ret >= 0) {
		/* get the actual port we started listen */
		len = SIZEOF_SOCKADDR(so);
		ret = getsockname(handle, &so.sa, &len);
		if (ret >= 0) {
			*port = sin_get_port(&so);

			/* start listening */
			if (listen(handle, 1) >= 0)
                                return g_io_channel_new(handle);
		}

	}

        /* error */
	close(handle);
	return NULL;
}
Пример #6
0
/* Accept a connection on a socket */
GIOChannel *net_accept(GIOChannel *handle, IPADDR *addr, int *port)
{
	union sockaddr_union so;
	int ret;
	socklen_t addrlen;

	g_return_val_if_fail(handle != NULL, NULL);

	addrlen = sizeof(so);
	ret = accept(g_io_channel_unix_get_fd(handle), &so.sa, &addrlen);

	if (ret < 0)
		return NULL;

	if (addr != NULL) sin_get_ip(&so, addr);
	if (port != NULL) *port = sin_get_port(&so);

#ifndef WIN32
	fcntl(ret, F_SETFL, O_NONBLOCK);
#endif
	return g_io_channel_new(ret);
}
Пример #7
0
static void session_restore_server(CONFIG_NODE *node)
{
	CHAT_PROTOCOL_REC *proto;
	SERVER_CONNECT_REC *conn;
	SERVER_REC *server;
	const char *chat_type, *address, *chatnet, *password, *nick;
        int port, handle;

        chat_type = config_node_get_str(node, "chat_type", NULL);
	address = config_node_get_str(node, "address", NULL);
	port = config_node_get_int(node, "port", 0);
	chatnet = config_node_get_str(node, "chatnet", NULL);
	password = config_node_get_str(node, "password", NULL);
	nick = config_node_get_str(node, "nick", NULL);
	handle = config_node_get_int(node, "handle", -1);

	if (chat_type == NULL || address == NULL || nick == NULL || handle < 0)
		return;

	proto = chat_protocol_find(chat_type);
	if (proto == NULL || proto->not_initialized) {
		if (handle < 0) close(handle);
		return;
	}

	conn = server_create_conn(proto->id, address, port,
				  chatnet, password, nick);
	if (conn != NULL) {
		conn->reconnection = TRUE;
		conn->connect_handle = g_io_channel_new(handle);

		server = proto->server_init_connect(conn);
		server->version = g_strdup(config_node_get_str(node, "version", NULL));
		server->session_reconnect = TRUE;
		signal_emit("session restore server", 2, server, node);

		proto->server_connect(server);
	}
}