コード例 #1
0
ファイル: ethconn.c プロジェクト: alepharchives/lingfs
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;
}
コード例 #2
0
ファイル: fsys.c プロジェクト: BillTheBest/Open-Vertex
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;
	}
}