Beispiel #1
0
static void puffout_strings(libvchan_t * con) {
    size_t sz, len;
    vchan_header_t head;

    DPRINTF(DBG_SERVER,"hello: waiting for hello message\n");

    /* Wait for hello */
    libvchan_wait(con);

    sz = libvchan_read(con, &head, sizeof(head));
    assert(sz == sizeof(head));
    assert(head.msg_type == MSG_HELLO);
    head.msg_type = MSG_ACK;
    len = head.len;

    DPRINTF(DBG_SERVER,"hello: sending hello msg ack\n");

    /* Send off ack */
    sz = libvchan_write(con, &head, sizeof(head));
    assert(sz == sizeof(head));

    DPRINTF(DBG_SERVER,"hello: waiting for string\n");

    /* Read data */
    libvchan_wait(con);
    sz = libvchan_read(con, &char_buf, len);
    assert(sz == len);

    DPRINTF(DBG_SERVER,"hello: got string: %s\n", char_buf);

    // head.msg_type = MSG_CONC;
    // sz = libvchan_write(con, &head, sizeof(head));
    // assert(sz == sizeof(head));
}
Beispiel #2
0
static void rec_packet(libvchan_t * con) {
    char done = 1;
    int data[4];
		struct camera_data ca;

    libvchan_wait(con);
    int readSize = libvchan_recv(con, data, 4*sizeof(int));
    assert(readSize == 4*sizeof(int));
    DVM("received bounding box packet\n");

    //here are your corners Lee!
    ca.bbox_l = data[0];
    ca.bbox_r = data[1];
    ca.bbox_t = data[2];
    ca.bbox_b = data[3];

    /* int xmid = ((r + l) / 2) - 160; */
    /* int ymid = ((b + t) / 2) - 100; */

    /* ymid = -1.0*ymid; //sign change (based on how the camera is oriented) */

    /* //here are your angles Lee! */
    /* ca.angle_x = ((float) xmid)*(0.00410666); */
    /* ca.angle_y = ((float) ymid)*(0.00410666); */

    if (camera_vm_Output_from_vm_0_write_camera_data(&ca)) {
	DVM("wrote bounding box\n");
    } else {
	DVM("failed to write bouding box\n");
    }

    DVM("camera_vm: sending ack\n");
    libvchan_send(con, &done, sizeof(char));
}
Beispiel #3
0
/**
        Wait fot the writes to finish, then notify the peer of closing
        On server side, it waits for the peer to acknowledge
*/
int libvchan_close(struct libvchan *ctrl)
{
	while (*ctrl->wr_prod != *ctrl->wr_cons)
		if (libvchan_wait(ctrl) < 0)
			return -1;
	if (ctrl->is_server) {
		ctrl->ring->server_closed = 1;
		do_notify(ctrl);
		while (!ctrl->ring->client_closed
		       && libvchan_wait(ctrl) == 0);
	} else {
		ctrl->ring->client_closed = 1;
		do_notify(ctrl);
	}
	return 0;
}
Beispiel #4
0
int libvchan_write(struct libvchan *ctrl, const void *data, size_t size)
{
    int avail;
    if (!libvchan_is_open(ctrl))
        return -1;
    if (ctrl->blocking) {
        size_t pos = 0;
        while (1) {
            avail = libvchan_buffer_space(ctrl);
            if (pos + avail > size)
                avail = size - pos;
            if (avail)
                pos += do_send(ctrl, data + pos, avail);
            if (pos == size)
                return pos;
            if (libvchan_wait(ctrl))
                return -1;
            if (!libvchan_is_open(ctrl))
                return -1;
        }
    } else {
        avail = libvchan_buffer_space(ctrl);
        if (size > avail)
            size = avail;
        if (size == 0)
            return 0;
        return do_send(ctrl, data, size);
    }
}
Beispiel #5
0
static void rec_packet(libvchan_t * con) {
    size_t sz;
    int x;
    char comp[6];
    vchan_packet_t pak;
    for(x = 0; x < NUM_PACKETS; x++) {
        sprintf(comp, "I%d", x);
        libvchan_wait(con);
        sz = libvchan_read(con, &pak, sizeof(pak));
        assert(sz == sizeof(pak));
        assert(strcmp(comp, pak.pnum) == 0);
    }

}
Beispiel #6
0
int libvchan_read(struct libvchan *ctrl, void *data, size_t size)
{
    while (1) {
        int avail = libvchan_data_ready(ctrl);
        if (avail && size > avail)
            size = avail;
        if (avail)
            return do_recv(ctrl, data, size);
        if (!libvchan_is_open(ctrl))
            return -1;
        if (!ctrl->blocking)
            return 0;
        if (libvchan_wait(ctrl))
            return -1;
    }
}
Beispiel #7
0
/**
 * returns 0 if no buffer space is available, -1 on error, or size on success
 */
int libvchan_send(struct libvchan *ctrl, const void *data, size_t size)
{
    int avail;
    while (1) {
        if (!libvchan_is_open(ctrl))
            return -1;
        avail = libvchan_buffer_space(ctrl);
        if (size <= avail)
            return do_send(ctrl, data, size);
        if (!ctrl->blocking)
            return 0;
        if (size > wr_ring_size(ctrl))
            return -1;
        if (libvchan_wait(ctrl))
            return -1;
    }
}
void init()
{
    mode_t old_umask;
    /* FIXME: This 0 is remote domain ID */
    ctrl_vchan = libvchan_server_init(0, VCHAN_BASE_PORT, 4096, 4096);
    if (!ctrl_vchan)
        handle_vchan_error("server_init");
    if (handle_handshake(ctrl_vchan) < 0)
        exit(1);
    old_umask = umask(0);
    trigger_fd = get_server_socket(QREXEC_AGENT_TRIGGER_PATH);
    umask(old_umask);
    register_exec_func(do_exec);

    /* wait for qrexec daemon */
    while (!libvchan_is_open(ctrl_vchan))
        libvchan_wait(ctrl_vchan);
}
Beispiel #9
0
/**
        may sleep (only if no data is available for reading);
        may return less data than requested;
        returns the amount of data processed, -1 on error or peer close
*/        
int libvchan_read(struct libvchan *ctrl, char *data, int size)
{
	int avail, avail_contig;
	int real_idx;
	while ((avail = libvchan_data_ready(ctrl)) == 0)
		if (libvchan_wait(ctrl) < 0)
			return -1;
	if (avail > size)
		avail = size;
	real_idx = (*ctrl->rd_cons) & (ctrl->rd_ring_size - 1);
	avail_contig = ctrl->rd_ring_size - real_idx;
	if (avail_contig < avail)
		avail = avail_contig;
	memcpy(data, ctrl->rd_ring + real_idx, avail);
	*ctrl->rd_cons += avail;
	if (do_notify(ctrl) < 0)
		return -1;
	return avail;
}
Beispiel #10
0
/**
        may sleep (only if no buffer space available);
        may write less data than requested;
        returns the amount of data processed, -1 on error or peer close
*/        
int libvchan_write(struct libvchan *ctrl, const char *data, int size)
{
	int avail, avail_contig;
	int real_idx;
	while ((avail = libvchan_buffer_space(ctrl)) == 0)
		if (libvchan_wait(ctrl) < 0)
			return -1;
	if (avail > size)
		avail = size;
	real_idx = (*ctrl->wr_prod) & (ctrl->wr_ring_size - 1);
	avail_contig = ctrl->wr_ring_size - real_idx;
	if (avail_contig < avail)
		avail = avail_contig;
	memcpy(ctrl->wr_ring + real_idx, data, avail);
	*ctrl->wr_prod += avail;
	if (do_notify(ctrl) < 0)
		return -1;
	return avail;
}
int wait_for_vchan_or_argfd_once(libvchan_t *vchan, int nfd, int *fd, fd_set * retset)
{
	fd_set rfds;
	int vfd, max = 0, ret, i;
	struct timeval tv = { 0, 1000000 };
	write_data(vchan, NULL, 0);	// trigger write of queued data, if any present
	vfd = libvchan_fd_for_select(vchan);
	FD_ZERO(&rfds);
	for (i = 0; i < nfd; i++) {
		int cfd = fd[i];
		FD_SET(cfd, &rfds);
		if (cfd > max)
			max = cfd;
	}
	FD_SET(vfd, &rfds);
	if (vfd > max)
		max = vfd;
	max++;
	ret = select(max, &rfds, NULL, NULL, &tv);
	if (ret < 0 && errno == EINTR)
		return -1;
	if (ret < 0) {
		perror("select");
		exit(1);
	}
	if (!libvchan_is_open(vchan)) {
		fprintf(stderr, "libvchan_is_eof\n");
		libvchan_close(vchan);
		if (vchan_at_eof != NULL) {
			vchan_at_eof();
			return -1;
		} else
			exit(0);
	}
	if (FD_ISSET(vfd, &rfds))
		// the following will never block; we need to do this to
		// clear libvchan_fd pending state 
		libvchan_wait(vchan);
	if (retset)
		*retset = rfds;
	return ret;
}
static int write_to_vchan(libvchan_t *ctrl, char *buf, int size)
{
    static int all = 0, waited = 0, nonwaited = 0, full = 0;
    ssize_t l;
    fd_set rfds;
    struct timeval tv = { 0, 0 };
    int ret, fd = libvchan_fd_for_select(ctrl);
    FD_ZERO(&rfds);
    FD_SET(fd, &rfds);
    all++;
    ret = select(fd + 1, &rfds, NULL, NULL, &tv);
    if (ret == -1) {
        pa_log("Failed to select() in vchan: %s",
               pa_cstrerror(errno));
        return -1;
    }
    if (ret) {
        if (libvchan_wait(ctrl) < 0) {
            pa_log("Failed libvchan_wait");
            return -1;
        }
        waited++;
    } else
        nonwaited++;
    if (libvchan_buffer_space(ctrl)) {
        l = libvchan_write(ctrl, buf, size);
    } else {
        l = -1;
        errno = EAGAIN;
        full++;
    }
    if ((all % 8000) == 0) {
        pa_log
        ("write_to_vchan: all=%d waited=%d nonwaited=%d full=%d\n",
         all, waited, nonwaited, full);
    }
    return l;
}
static void thread_func(void *userdata)
{
    struct userdata *u = userdata;
    char buf[2048]; // max ring buffer size

    pa_assert(u);

    pa_log_debug("Thread starting up");

    pa_thread_mq_install(&u->thread_mq);
    for (;;) {
        struct pollfd *play_pollfd;
        struct pollfd *rec_pollfd;
        int ret;

        play_pollfd = pa_rtpoll_item_get_pollfd(u->play_rtpoll_item, NULL);
        rec_pollfd = pa_rtpoll_item_get_pollfd(u->rec_rtpoll_item, NULL);

        if (play_pollfd->revents & POLLIN) {
            if (libvchan_wait(u->play_ctrl) < 0)
                goto fail;
            play_pollfd->revents = 0;
        }

        if (rec_pollfd->revents & POLLIN) {
            if (libvchan_wait(u->rec_ctrl) < 0)
                goto fail;
            rec_pollfd->revents = 0;
        }

        /* Render some data and write it to the fifo */
        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {

            if (u->sink->thread_info.rewind_requested)
                pa_sink_process_rewind(u->sink, 0);

            if (libvchan_buffer_space(u->play_ctrl)) {
                if (process_sink_render(u) < 0)
                    goto fail;
            }
        }

        if (u->source->thread_info.state == PA_SOURCE_RUNNING) {
            while (libvchan_data_ready(u->rec_ctrl)) {
                if (process_source_data(u) < 0)
                    goto fail;
            }
        } else {
            /* discard the data */
            if (libvchan_data_ready(u->rec_ctrl))
                if (libvchan_read(u->rec_ctrl, buf, sizeof(buf)) < 0)
                    goto fail;
        }

        /* Hmm, nothing to do. Let's sleep */
        play_pollfd->events = POLLIN;
        rec_pollfd->events = POLLIN;

#if PA_CHECK_VERSION(6,0,0)
        if ((ret = pa_rtpoll_run(u->rtpoll)) < 0)
#else
        if ((ret = pa_rtpoll_run(u->rtpoll, true)) < 0)
#endif
            goto fail;

        if (ret == 0)
            goto finish;
    }

fail:
    /* If this was no regular exit from the loop we have to continue
     * processing messages until we received PA_MESSAGE_SHUTDOWN */
    pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core),
                      PA_CORE_MESSAGE_UNLOAD_MODULE, u->module,
                      0, NULL, NULL);
    pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);

finish:
    pa_log_debug("Thread shutting down");
}
int main(int argc, char **argv)
{
    int opt;
    char *domname = NULL;
    libvchan_t *data_vchan = NULL;
    int data_port;
    int data_domain;
    int msg_type;
    int s;
    int just_exec = 0;
    int connect_existing = 0;
    char *local_cmdline = NULL;
    char *remote_cmdline = NULL;
    char *request_id;
    char *src_domain_name = NULL;
    int src_domain_id = 0; /* if not -c given, the process is run in dom0 */
    struct service_params svc_params;
    while ((opt = getopt(argc, argv, "d:l:ec:tT")) != -1) {
        switch (opt) {
            case 'd':
                domname = strdup(optarg);
                break;
            case 'l':
                local_cmdline = strdup(optarg);
                break;
            case 'e':
                just_exec = 1;
                break;
            case 'c':
                parse_connect(optarg, &request_id, &src_domain_name, &src_domain_id);
                connect_existing = 1;
                is_service = 1;
                break;
            case 't':
                replace_esc_stdout = 1;
                break;
            case 'T':
                replace_esc_stderr = 1;
                break;
            default:
                usage(argv[0]);
        }
    }
    if (optind >= argc || !domname)
        usage(argv[0]);
    remote_cmdline = argv[optind];

    register_exec_func(&do_exec);

    if (just_exec + connect_existing + (local_cmdline != 0) > 1) {
        fprintf(stderr, "ERROR: only one of -e, -l, -c can be specified\n");
        usage(argv[0]);
    }

    if (strcmp(domname, "dom0") == 0 && !connect_existing) {
        fprintf(stderr, "ERROR: when target domain is 'dom0', -c must be specified\n");
        usage(argv[0]);
    }

    if (strcmp(domname, "dom0") == 0) {
        if (connect_existing) {
            msg_type = MSG_SERVICE_CONNECT;
            strncpy(svc_params.ident, request_id, sizeof(svc_params.ident));
        } else if (just_exec)
            msg_type = MSG_JUST_EXEC;
        else
            msg_type = MSG_EXEC_CMDLINE;
        assert(src_domain_name);
        setenv("QREXEC_REMOTE_DOMAIN", src_domain_name, 1);
        s = connect_unix_socket(src_domain_name);
        negotiate_connection_params(s,
                0, /* dom0 */
                msg_type,
                connect_existing ? (void*)&svc_params : (void*)remote_cmdline,
                connect_existing ? sizeof(svc_params) : strlen(remote_cmdline) + 1,
                &data_domain,
                &data_port);

        prepare_local_fds(remote_cmdline);
        if (connect_existing)
            data_vchan = libvchan_client_init(data_domain, data_port);
        else {
            data_vchan = libvchan_server_init(data_domain, data_port,
                    VCHAN_BUFFER_SIZE, VCHAN_BUFFER_SIZE);
            while (data_vchan && libvchan_is_open(data_vchan) == VCHAN_WAITING)
                libvchan_wait(data_vchan);
        }
        if (!data_vchan || !libvchan_is_open(data_vchan)) {
            fprintf(stderr, "Failed to open data vchan connection\n");
            do_exit(1);
        }
        if (handle_agent_handshake(data_vchan, connect_existing) < 0)
            do_exit(1);
        select_loop(data_vchan);
    } else {
        if (just_exec)
            msg_type = MSG_JUST_EXEC;
        else
            msg_type = MSG_EXEC_CMDLINE;
        s = connect_unix_socket(domname);
        negotiate_connection_params(s,
                src_domain_id,
                msg_type,
                remote_cmdline,
                strlen(remote_cmdline) + 1,
                &data_domain,
                &data_port);
        close(s);
        setenv("QREXEC_REMOTE_DOMAIN", domname, 1);
        prepare_local_fds(local_cmdline);
        if (connect_existing) {
            s = connect_unix_socket(src_domain_name);
            send_service_connect(s, request_id, data_domain, data_port);
            close(s);
        } else {
            data_vchan = libvchan_server_init(data_domain, data_port,
                    VCHAN_BUFFER_SIZE, VCHAN_BUFFER_SIZE);
            if (!data_vchan) {
                fprintf(stderr, "Failed to start data vchan server\n");
                do_exit(1);
            }
            while (libvchan_is_open(data_vchan) == VCHAN_WAITING)
                libvchan_wait(data_vchan);
            if (!libvchan_is_open(data_vchan)) {
                fprintf(stderr, "Failed to open data vchan connection\n");
                do_exit(1);
            }
            if (handle_agent_handshake(data_vchan, 0) < 0)
                do_exit(1);
            select_loop(data_vchan);
        }
    }
    return 0;
}
static void select_loop(libvchan_t *vchan)
{
    fd_set select_set;
    fd_set wr_set;
    int max_fd;
    int ret;
    int vchan_fd;
    sigset_t selectmask;
    struct timespec zero_timeout = { 0, 0 };
    struct timespec select_timeout = { 10, 0 };
    struct buffer stdin_buf;

    sigemptyset(&selectmask);
    sigaddset(&selectmask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &selectmask, NULL);
    sigemptyset(&selectmask);
    buffer_init(&stdin_buf);
    /* remember to set back to blocking mode before closing the FD - this may
     * be not the only copy and some processes may misbehave when get
     * nonblocking FD for input/output
     */
    set_nonblock(local_stdin_fd);

    for (;;) {
        vchan_fd = libvchan_fd_for_select(vchan);
        FD_ZERO(&select_set);
        FD_ZERO(&wr_set);
        FD_SET(vchan_fd, &select_set);
        max_fd = vchan_fd;
        if (local_stdout_fd != -1 &&
                (size_t)libvchan_buffer_space(vchan) > sizeof(struct msg_header)) {
            FD_SET(local_stdout_fd, &select_set);
            if (local_stdout_fd > max_fd)
                max_fd = local_stdout_fd;
        }
        if (child_exited && local_stdout_fd == -1)
            check_child_status(vchan);
        if (local_stdin_fd != -1 && buffer_len(&stdin_buf)) {
            FD_SET(local_stdin_fd, &wr_set);
            if (local_stdin_fd > max_fd)
                max_fd = local_stdin_fd;
        }
        if ((local_stdin_fd == -1 || buffer_len(&stdin_buf) == 0) &&
                libvchan_data_ready(vchan) > 0) {
            /* check for other FDs, but exit immediately */
            ret = pselect(max_fd + 1, &select_set, &wr_set, NULL,
                    &zero_timeout, &selectmask);
        } else
            ret = pselect(max_fd + 1, &select_set, &wr_set, NULL,
                    &select_timeout, &selectmask);
        if (ret < 0) {
            if (errno == EINTR && local_pid > 0) {
                continue;
            } else {
                perror("select");
                do_exit(1);
            }
        }
        if (ret == 0) {
            if (!libvchan_is_open(vchan)) {
                /* remote disconnected witout a proper signaling */
                do_exit(1);
            }
        }
        if (FD_ISSET(vchan_fd, &select_set))
            libvchan_wait(vchan);
        if (buffer_len(&stdin_buf) &&
                local_stdin_fd != -1 &&
                FD_ISSET(local_stdin_fd, &wr_set)) {
            if (flush_client_data(local_stdin_fd, &stdin_buf) == WRITE_STDIN_ERROR) {
                perror("write stdin");
                close(local_stdin_fd);
                local_stdin_fd = -1;
            }
        }
        while (libvchan_data_ready(vchan))
            if (handle_vchan_data(vchan, &stdin_buf) != WRITE_STDIN_OK)
                break;

        if (local_stdout_fd != -1
                && FD_ISSET(local_stdout_fd, &select_set))
            handle_input(vchan);
    }
}