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 *)ðconn->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; }
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; } }