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); }
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); }
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; } }
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; }
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; } }