/* -1: connection got closed, 0: nothing to read, n: read n bytes */ gssize stream_read(server *srv, stream *s, char *buf, gssize bufsize) { gssize len; while (-1 == (len = read(s->fd, buf, bufsize))) { switch (errno) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif /* nothing to read */ return 0; case ECONNRESET: return stream_closed(srv, s); case EINTR: /* try again */ break; default: g_message("read error: %s", g_strerror(errno)); stream_close(srv, s, s->other); return -1; } } if (0 == len) { /* connection closed */ return stream_closed(srv, s); } return len; }
/* -1: connection closed, n: wrote n bytes */ gssize stream_write(server *srv, stream *s) { gssize len; while (-1 == (len = write(s->fd, s->buffer->str, s->buffer->len))) { switch (errno) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif /* try again later */ return 0; case ECONNRESET: case EPIPE: return stream_closed(srv, s); case EINTR: /* try again */ break; default: g_message("write error: %s", g_strerror(errno)); stream_close(srv, s, s->other); return -1; } } g_string_erase(s->buffer, 0, len); if (s->buffer->len == 0) { if (s->other->closed) return stream_closed(srv, s); ev_io_rem_events(srv->loop, &s->watcher, EV_WRITE); } if (s->buffer->len < MAX_STREAM_BUF_SIZE && !s->other->closed) ev_io_add_events(srv->loop, &s->other->watcher, EV_READ); return 0; }
static void call_op(grpc_call_element *elem, grpc_call_element *from_elemn, grpc_call_op *op) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; grpc_mdelem *md; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); switch (op->type) { case GRPC_RECV_METADATA: md = op->data.metadata; if (md->key == chand->path_key) { calld->path = grpc_mdstr_ref(md->value); grpc_mdelem_unref(md); } else if (md->key == chand->authority_key) { calld->host = grpc_mdstr_ref(md->value); grpc_mdelem_unref(md); } else { grpc_call_recv_metadata(elem, md); } break; case GRPC_RECV_END_OF_INITIAL_METADATA: start_new_rpc(elem); grpc_call_initial_metadata_complete(elem); break; case GRPC_RECV_MESSAGE: grpc_call_recv_message(elem, op->data.message); op->done_cb(op->user_data, GRPC_OP_OK); break; case GRPC_RECV_HALF_CLOSE: read_closed(elem); break; case GRPC_RECV_FINISH: stream_closed(elem); break; case GRPC_RECV_DEADLINE: grpc_call_set_deadline(elem, op->data.deadline); ((call_data *)elem->call_data)->deadline = op->data.deadline; break; default: GPR_ASSERT(op->dir == GRPC_CALL_DOWN); grpc_call_next_op(elem, op); break; } }
static gssize stream_closed(server *srv, stream *s) { ev_io_stop(srv->loop, &s->watcher); if (s->fd != -1) { shutdown(s->fd, SHUT_RDWR); close(s->fd); s->fd = -1; } s->closed = TRUE; g_string_truncate(s->buffer, 0); if (s->other->closed) return -1; if (s->other->buffer->len == 0) { /* nothing to send on the other side, so close that too. */ return stream_closed(srv, s->other); } else { /* we can't send the data, so we don't read it */ /* other stream gets closed if its buffer gets empty */ ev_io_rem_events(srv->loop, &s->other->watcher, EV_READ); return 0; } }