예제 #1
0
파일: socket.c 프로젝트: dreamsxin/GNU-Hurd
/* Return a new connection from a socket previously listened.  */
error_t
S_socket_accept (struct sock_user *user,
                 mach_port_t *port, mach_msg_type_name_t *port_type,
                 mach_port_t *peer_addr_port,
                 mach_msg_type_name_t *peer_addr_port_type)
{
    error_t err;
    struct sock *sock;

    if (!user)
        return EOPNOTSUPP;

    sock = user->sock;

    err = ensure_connq (sock);
    if (!err)
    {
        struct timespec noblock = {0, 0};
        struct sock *peer_sock;

        err = connq_listen (sock->listen_queue,
                            (sock->flags & PFLOCAL_SOCK_NONBLOCK) ? &noblock : NULL,
                            &peer_sock);
        if (!err)
        {
            struct addr *peer_addr;
            *port_type = MACH_MSG_TYPE_MAKE_SEND;
            err = sock_create_port (peer_sock, port);
            if (!err)
                err = sock_get_addr (peer_sock, &peer_addr);
            if (!err)
            {
                *peer_addr_port = ports_get_right (peer_addr);
                *peer_addr_port_type = MACH_MSG_TYPE_MAKE_SEND;
                ports_port_deref (peer_addr);
            }
            else
            {
                /* TEAR DOWN THE CONNECTION XXX */
            }
        }
    }

    return err;
}
예제 #2
0
파일: sock.c 프로젝트: forthewatch/xdm
int make_server(const char *host, const char *port)
{
	struct sockaddr addr;
	int fd;
	int ret;

	ret = sock_get_addr(host, port, &addr);
	if(ret < 0) {
		return -1;
	}

	fd = sock_server_create(&addr);
	if(fd < 0) {
		return -1;
	}

	return fd;
}
예제 #3
0
파일: socket.c 프로젝트: dreamsxin/GNU-Hurd
/* Find out the name of a socket.  */
error_t
S_socket_name (struct sock_user *user,
               mach_port_t *addr_port, mach_msg_type_name_t *addr_port_type)
{
    error_t err;
    struct addr *addr;

    if (!user)
        return EOPNOTSUPP;

    err = sock_get_addr (user->sock, &addr);
    if (err)
        return err;

    *addr_port = ports_get_right (addr);
    *addr_port_type = MACH_MSG_TYPE_MAKE_SEND;
    ports_port_deref (addr);

    return 0;
}
예제 #4
0
파일: node.c 프로젝트: forthewatch/xdm
int node_connect(int link, struct node *local_node, struct node *remote_node)
{
	int fd;
	int ret;
	struct sockaddr local_addr;
	struct sockaddr remote_addr;
	struct sock_packet *sock_pkt;

	fd_set rset;
	fd_set wset;
	struct timeval tv;
	int error;
	int len;

	if(link == NODE_DATA_LINK
			&& remote_node->data_conn_state == NODE_DFD_CONNECTED) {
		return 0;
	}

	if(link == NODE_META_LINK
			&& remote_node->meta_conn_state == NODE_MFD_CONNECTED) {
		return 0;
	}

	fd = sock_create();
	if(fd < 0) {
		return -1;
	}

	if(sock_get_addr(local_node->remote_ip, NULL, &local_addr) < 0) {
		goto err;
	}

	if(sock_get_addr(remote_node->remote_ip, remote_node->remote_port, &remote_addr) < 0) {
		goto err;
	}

	if(sock_bind(fd, &local_addr) < 0) {
		goto err;
	}

	sock_set_nonblock(fd);
	ret = sock_connect(fd, &remote_addr);

	if(ret < 0 && errno != EINPROGRESS) {
		goto err;
	} else if(ret == 0) {
		goto done;
	} else {
		FD_ZERO(&rset);
		FD_SET(fd, &rset);
		wset = rset;

		tv.tv_sec = SOCK_TIMEOUT;
		tv.tv_usec = 0;

		ret = select(SELECT_MAX_FDS, &rset, &wset, NULL, &tv);
		if(ret <= 0) {
			goto err;
		}

		error = 0;
		len = sizeof(int);
		if(FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
			if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
				goto err;
			}
		}

		if(error) {
			goto err;
		}

		goto done;
	}

done:
	if(link == NODE_DATA_LINK) {
		sock_pkt = create_sock_packet(local_node->id, DATA_HANDSHAKE);
	} else if(link == NODE_META_LINK) {
		sock_pkt = create_sock_packet(local_node->id, META_HANDSHAKE);
	} else {
		goto err;
	}

	if(sock_pkt == NULL) {
		goto err;
	}

	sock_clear_nonblock(fd);
	sock_packet_send(fd, sock_pkt);
	free_sock_packet(sock_pkt);

	if(link == NODE_DATA_LINK) {
		remote_node->dfd = fd;
	} else if(link == NODE_META_LINK) {
		remote_node->mfd = fd;
	}

	return 0;

err:
	sock_close(fd);
	return -1;
}
예제 #5
0
파일: socket.c 프로젝트: dreamsxin/GNU-Hurd
/* Send data over a socket, possibly including Mach ports.  */
error_t
S_socket_send (struct sock_user *user, struct addr *dest_addr, int flags,
               char *data, size_t data_len,
               mach_port_t *ports, size_t num_ports,
               char *control, size_t control_len,
               size_t *amount)
{
    error_t err = 0;
    struct pipe *pipe;
    struct sock *sock, *dest_sock;
    struct addr *source_addr;

    if (!user)
        return EOPNOTSUPP;

    sock = user->sock;

    if (flags & MSG_OOB)
        /* BSD local sockets don't support OOB data.  */
        return EOPNOTSUPP;

    if (dest_addr)
    {
        err = addr_get_sock (dest_addr, &dest_sock);
        if (err == EADDRNOTAVAIL)
            /* The server went away.  */
            err = ECONNREFUSED;
        if (err)
            return err;
        if (sock->pipe_class != dest_sock->pipe_class)
            /* Sending to a different type of socket!  */
            err = EINVAL;		/* ? XXX */
    }
    else
        dest_sock = 0;

    /* We could provide a source address for all writes, but we
       only do so for connectionless sockets because that's the
       only place it's required, and it's more efficient not to.  */
    if (!err && sock->pipe_class->flags & PIPE_CLASS_CONNECTIONLESS)
        err = sock_get_addr (sock, &source_addr);
    else
        source_addr = NULL;

    if (!err)
    {
        if (dest_sock)
            /* Grab the destination socket's read pipe directly, and stuff data
               into it.  This is not quite the usage sock_acquire_read_pipe was
               intended for, but it will work, as the only inappropriate errors
               occur on a broken pipe, which shouldn't be possible with the sort of
               sockets with which we can use socket_send...  XXXX */
            err = sock_acquire_read_pipe (dest_sock, &pipe);
        else
            /* No address, must be a connected socket...  */
            err = sock_acquire_write_pipe (sock, &pipe);

        if (!err)
        {
            err = pipe_send (pipe, sock->flags & PFLOCAL_SOCK_NONBLOCK,
                             source_addr, data, data_len,
                             control, control_len, ports, num_ports,
                             amount);
            if (dest_sock)
                pipe_release_reader (pipe);
            else
                pipe_release_writer (pipe);
        }

        if (err)
            /* The send failed, so free any resources it would have consumed
               (mig gets rid of memory, but we have to do everything else). */
        {
            if (source_addr)
                ports_port_deref (source_addr);
            while (num_ports-- > 0)
                mach_port_deallocate (mach_task_self (), *ports++);
        }
    }

    if (dest_sock)
        sock_deref (dest_sock);

    return err;
}