Beispiel #1
0
static void
sp_socksrv_notify(Spfd *spfd, void *aux)
{
    int csock;
    Spsrv *srv;
    Spconn *conn;
    Socksrv *ss;
    struct sockaddr_in caddr;
    socklen_t caddrlen;
    char buf[64];

    srv = aux;
    ss = srv->srvaux;

    if (!spfd_can_read(spfd))
        return;

    spfd_read(spfd, buf, 0);
    caddrlen = sizeof(caddr);
    csock = accept(ss->sock, (struct sockaddr *) &caddr, &caddrlen);
    if (csock<0) {
        if (!ss->shutdown)
            return;

        close(ss->sock);
        if (sp_socksrv_connect(ss) < 0)
            fprintf(stderr, "error while reconnecting: %d\n", errno);
        return;
    }

    fcntl(csock, F_SETFD, FD_CLOEXEC);
    snprintf(buf, sizeof(buf), "%s!%d", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
    if (!(conn = sp_conn_create(srv, strdup(buf), csock, csock)))
        close(csock);
}
Beispiel #2
0
static void
pip_read(Xfilepipe *p)
{
	int n;

//	fprintf(stderr, "pip_read %p %d %d %d\n", p, spfd_can_read(p->lspfd), spfd_can_write(p->lspfd), spfd_has_error(p->lspfd));
	if (spfd_has_error(p->lspfd)) {
		pip_read_eof(p);
		pip_read_buf(p);
		return;
	}

	if (p->direction != Read)
		return;

	if (p->buflen < p->bufsize) {
		n = spfd_read(p->lspfd, p->buf + p->buflen, p->bufsize - p->buflen);
		if (n > 0) {
//			fprintf(stderr, "pip_read %p read %d bytes\n", p, n);
			p->buflen += n;
		}
	}

	pip_read_buf(p);
}
Beispiel #3
0
static void
pip_read_eof(Xfilepipe *p)
{
	int n;
	char *buf;

	/* if the pipe was closed, we are not going to be called anymore
	   so we need to read all the data now */
	while (1) {
		n = 32;
		if (p->buflen+n > p->bufsize) {
			buf = realloc(p->buf, p->bufsize + n);
			if (!buf) 
				return;

			p->buf = buf;
			p->bufsize += n;
		}

		n = spfd_read(p->lspfd, p->buf + p->buflen, p->bufsize - p->buflen);
		if (n <= 0)
			break;

		p->buflen += n;
	}
}
Beispiel #4
0
int 
spcfd_read(Spcfd *spcfd, void *buf, int buflen)
{
	int n;

	if (spcfd->spfd)
		return spfd_read(spcfd->spfd, buf, buflen);

	if (spcfd->flags & Reof)
		return 0;

	if (spcfd->rpos == 0) {
		sp_werror("read operation would block", EIO);
		return -1;
	}

	n = buflen;
	if (n > spcfd->rpos)
		n = spcfd->rpos;

	memmove(buf, spcfd->rbuf, n);
	if (n < spcfd->rpos)
		memmove(spcfd->rbuf, spcfd->rbuf + n, spcfd->rpos - n);
	spcfd->rpos -= n;

	spcfd_send_read_request(spcfd);
	return n;
}
Beispiel #5
0
static int
sp_ethconn_read(Spconn *conn)
{
	Spsrv *srv = conn->srv;
	Spfcall *fc;
	Spreq *req;
	Spethconn *ethconn = conn->caux;

	printf("reading...\n");

	/* if we are sending Enomem error back, block all reading */
	if (srv->enomem)
		return 0;

	if (!conn->ireqs) {
		fc = sp_conn_new_incall(conn);
		if (!fc)
			return 0;

		fc->size = 0;
		conn->ireqs = sp_req_alloc(conn, fc);
		if (!conn->ireqs)
			return 0;
	}
		
	fc = conn->ireqs->tcall;

	//
	// ethconn->saddr is later reused for sending. This is safe as 9P connection
	// is initated by the client.
	//

	socklen_t sa_len = sizeof(ethconn->saddr);
	spfd_read(ethconn->spfd, 0, 0);
	int n = recvfrom(ethconn->fd, fc->pkt, conn->msize, 0,
			(struct sockaddr *)&ethconn->saddr, &sa_len);
	if (srv->debuglevel > 1)
		fprintf(stderr, "sp_ethconn_read: recvfrom returns %d\n", n);
	if (n == 0)
		return -1;
	else if (n < 0)
	{
		if (srv->debuglevel > 0)
			fprintf(stderr, "sp_ethconn_read: recvfrom error: %s\n", strerror(errno));
		return 0;
	}

	// packets of other protocols may still be visible on the interface
	assert(ethconn->saddr.sll_protocol == htons(EXP_9P_ETH));

	if (n < 4)
		return 0;

	int exp_size = fc->pkt[0] | (fc->pkt[1]<<8) | (fc->pkt[2]<<16) | (fc->pkt[3]<<24);
	if (srv->debuglevel > 1)
		fprintf(stderr, "sp_ethconn_read: expected size %d\n", exp_size);
	if (exp_size != n -4) 	// +4: csum field
		return 0;

	fc->size = exp_size;

	if (!sp_deserialize(fc, fc->pkt, conn->dotu)) {
		fprintf(stderr, "error while deserializing\n");
		close(ethconn->fd);
		return 0;
	}

	if (srv->debuglevel > 0) {
		fprintf(stderr, "<<< (%p) ", conn);
		sp_printfcall(stderr, fc, conn->dotu);
		fprintf(stderr, "\n");
	}

	req = conn->ireqs;
	req->tag = req->tcall->tag;
	conn->ireqs = NULL;
	sp_srv_process_req(req);

	return 0;
}
Beispiel #6
0
static void
spc_fd_read(Spcfsys *fs)
{
	int n, size;
	Spfcall *fc;
	Spcreq *req, *preq;

	if (!fs->ifcall) {
		fs->ifcall = spc_fcall_alloc(fs->msize);
		if (!fs->ifcall) {
			spc_disconnect_fsys(fs);
			return;
		}

		fs->ifcall->size = 0;
	}

	fc = fs->ifcall;
	n = spfd_read(fs->spfd, fc->pkt + fc->size, fs->msize - fc->size);
	if (n <= 0) {
		if (n == 0)
			spc_disconnect_fsys(fs);
		return;
	}

	fc->size += n;

again:
	if (fc->size < 4)
		return;

	n = fc->size;
	size = fc->pkt[0] | (fc->pkt[1]<<8) | (fc->pkt[2]<<16) | (fc->pkt[3]<<24);
	if (size > fs->msize) {
		sp_werror("invalid fcall size greater than msize", EIO);
		spc_disconnect_fsys(fs);
		return;
	}

	if (n < size)
		return;

	if (!sp_deserialize(fc, fc->pkt, fs->dotu)) {
		sp_werror("invalid fcall", EIO);
		spc_disconnect_fsys(fs);
		return;
	}

	if (spc_chatty) {
		fprintf(stderr, "-->>> (%p) ", fs);
		sp_printfcall(stderr, fc, fs->dotu);
		fprintf(stderr, "\n");
	}

	fs->ifcall = spc_fcall_alloc(fs->msize);
	if (!fs->ifcall) {
		spc_disconnect_fsys(fs);
		return;
	}

	if (n > size)
		memmove(fs->ifcall->pkt, fc->pkt + size, n - size);

	fs->ifcall->size = n - size;

	for(preq = NULL, req = fs->sent_reqs; req != NULL; preq = req, req = req->next)
		if (fc->tag == req->tag) 
			break;

	if (!req) {
		sp_werror("unexpected fcall", EIO);
		free(fc);
		return;
	}

	if (preq)
		preq->next = req->next;
	else
		fs->sent_reqs = req->next;

	if (fc->type!=Rerror && req->tc->type+1!=fc->type) {
		sp_werror(Emismatch, EIO);
		free(fc);
		fc = NULL;
	}

	(*req->cb)(req->cba, fc);
	if (fs->destroyed) {
		free(req);
		return;
	}

	if (!req->flushed) {
		spc_put_id(fs->tagpool, req->tag);
		free(req);
	}

	if (fs->ifcall->size) {
		fc = fs->ifcall;
		goto again;
	}
}