示例#1
0
static int zlib_body(z_stream* zs, gpr_slice_buffer* input,
                     gpr_slice_buffer* output,
                     int (*flate)(z_stream* zs, int flush)) {
  int r;
  int flush;
  size_t i;
  gpr_slice outbuf = gpr_slice_malloc(OUTPUT_BLOCK_SIZE);
  const uInt uint_max = ~(uInt)0;

  GPR_ASSERT(GPR_SLICE_LENGTH(outbuf) <= uint_max);
  zs->avail_out = (uInt)GPR_SLICE_LENGTH(outbuf);
  zs->next_out = GPR_SLICE_START_PTR(outbuf);
  flush = Z_NO_FLUSH;
  for (i = 0; i < input->count; i++) {
    if (i == input->count - 1) flush = Z_FINISH;
    GPR_ASSERT(GPR_SLICE_LENGTH(input->slices[i]) <= uint_max);
    zs->avail_in = (uInt)GPR_SLICE_LENGTH(input->slices[i]);
    zs->next_in = GPR_SLICE_START_PTR(input->slices[i]);
    do {
      if (zs->avail_out == 0) {
        gpr_slice_buffer_add_indexed(output, outbuf);
        outbuf = gpr_slice_malloc(OUTPUT_BLOCK_SIZE);
        GPR_ASSERT(GPR_SLICE_LENGTH(outbuf) <= uint_max);
        zs->avail_out = (uInt)GPR_SLICE_LENGTH(outbuf);
        zs->next_out = GPR_SLICE_START_PTR(outbuf);
      }
      r = flate(zs, flush);
      if (r == Z_STREAM_ERROR) {
        gpr_log(GPR_INFO, "zlib: stream error");
        goto error;
      }
    } while (zs->avail_out == 0);
    if (zs->avail_in) {
      gpr_log(GPR_INFO, "zlib: not all input consumed");
      goto error;
    }
  }

  GPR_ASSERT(outbuf.refcount);
  outbuf.data.refcounted.length -= zs->avail_out;
  gpr_slice_buffer_add_indexed(output, outbuf);

  return 1;

error:
  gpr_slice_unref(outbuf);
  return 0;
}
示例#2
0
void gpr_slice_buffer_add(gpr_slice_buffer *sb, gpr_slice s) {
  size_t n = sb->count;
  /* if both the last slice in the slice buffer and the slice being added
     are inlined (that is, that they carry their data inside the slice data
     structure), and the back slice is not full, then concatenate directly
     into the back slice, preventing many small slices being passed into
     writes */
  if (!s.refcount && n) {
    gpr_slice *back = &sb->slices[n - 1];
    if (!back->refcount && back->data.inlined.length < GPR_SLICE_INLINED_SIZE) {
      if (s.data.inlined.length + back->data.inlined.length <=
          GPR_SLICE_INLINED_SIZE) {
        memcpy(back->data.inlined.bytes + back->data.inlined.length,
               s.data.inlined.bytes, s.data.inlined.length);
        back->data.inlined.length =
            (uint8_t)(back->data.inlined.length + s.data.inlined.length);
      } else {
        size_t cp1 = GPR_SLICE_INLINED_SIZE - back->data.inlined.length;
        memcpy(back->data.inlined.bytes + back->data.inlined.length,
               s.data.inlined.bytes, cp1);
        back->data.inlined.length = GPR_SLICE_INLINED_SIZE;
        maybe_embiggen(sb);
        back = &sb->slices[n];
        sb->count = n + 1;
        back->refcount = NULL;
        back->data.inlined.length = (uint8_t)(s.data.inlined.length - cp1);
        memcpy(back->data.inlined.bytes, s.data.inlined.bytes + cp1,
               s.data.inlined.length - cp1);
      }
      sb->length += s.data.inlined.length;
      return; /* early out */
    }
  }
  gpr_slice_buffer_add_indexed(sb, s);
}
示例#3
0
static void ru_allocated_slices(grpc_exec_ctx *exec_ctx, void *arg,
                                grpc_error *error) {
  grpc_resource_user_slice_allocator *slice_allocator = arg;
  if (error == GRPC_ERROR_NONE) {
    for (size_t i = 0; i < slice_allocator->count; i++) {
      gpr_slice_buffer_add_indexed(
          slice_allocator->dest, ru_slice_create(slice_allocator->resource_user,
                                                 slice_allocator->length));
    }
  }
  grpc_closure_run(exec_ctx, &slice_allocator->on_done, GRPC_ERROR_REF(error));
}
示例#4
0
void gpr_slice_buffer_trim_end(gpr_slice_buffer *sb, size_t n,
                               gpr_slice_buffer *garbage) {
  GPR_ASSERT(n <= sb->length);
  sb->length -= n;
  for (;;) {
    size_t idx = sb->count - 1;
    gpr_slice slice = sb->slices[idx];
    size_t slice_len = GPR_SLICE_LENGTH(slice);
    if (slice_len > n) {
      sb->slices[idx] = gpr_slice_split_head(&slice, slice_len - n);
      gpr_slice_buffer_add_indexed(garbage, slice);
      return;
    } else if (slice_len == n) {
      gpr_slice_buffer_add_indexed(garbage, slice);
      sb->count = idx;
      return;
    } else {
      gpr_slice_buffer_add_indexed(garbage, slice);
      n -= slice_len;
      sb->count = idx;
    }
  }
}
示例#5
0
/* begin a new frame: reserve off header space, remember how many bytes we'd
   output before beginning */
static void begin_frame(framer_state *st) {
  st->header_idx =
      gpr_slice_buffer_add_indexed(st->output, gpr_slice_malloc(9));
  st->output_length_at_start_of_frame = st->output->length;
}
示例#6
0
static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
  struct msghdr msg;
  struct iovec iov[MAX_READ_IOVEC];
  ssize_t read_bytes;
  size_t i;

  GPR_ASSERT(!tcp->finished_edge);
  GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC);
  GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC);
  GPR_TIMER_BEGIN("tcp_continue_read", 0);

  while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) {
    gpr_slice_buffer_add_indexed(tcp->incoming_buffer,
                                 gpr_slice_malloc(tcp->slice_size));
  }
  for (i = 0; i < tcp->incoming_buffer->count; i++) {
    iov[i].iov_base = GPR_SLICE_START_PTR(tcp->incoming_buffer->slices[i]);
    iov[i].iov_len = GPR_SLICE_LENGTH(tcp->incoming_buffer->slices[i]);
  }

  msg.msg_name = NULL;
  msg.msg_namelen = 0;
  msg.msg_iov = iov;
  msg.msg_iovlen = tcp->iov_size;
  msg.msg_control = NULL;
  msg.msg_controllen = 0;
  msg.msg_flags = 0;

  GPR_TIMER_BEGIN("recvmsg", 1);
  do {
    read_bytes = recvmsg(tcp->fd, &msg, 0);
  } while (read_bytes < 0 && errno == EINTR);
  GPR_TIMER_END("recvmsg", 0);

  if (read_bytes < 0) {
    /* NB: After calling call_read_cb a parallel call of the read handler may
     * be running. */
    if (errno == EAGAIN) {
      if (tcp->iov_size > 1) {
        tcp->iov_size /= 2;
      }
      /* We've consumed the edge, request a new one */
      grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
    } else {
      /* TODO(klempner): Log interesting errors */
      gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
      call_read_cb(exec_ctx, tcp, 0);
      TCP_UNREF(exec_ctx, tcp, "read");
    }
  } else if (read_bytes == 0) {
    /* 0 read size ==> end of stream */
    gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
    call_read_cb(exec_ctx, tcp, 0);
    TCP_UNREF(exec_ctx, tcp, "read");
  } else {
    GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length);
    if ((size_t)read_bytes < tcp->incoming_buffer->length) {
      gpr_slice_buffer_trim_end(
          tcp->incoming_buffer,
          tcp->incoming_buffer->length - (size_t)read_bytes,
          &tcp->last_read_buffer);
    } else if (tcp->iov_size < MAX_READ_IOVEC) {
      ++tcp->iov_size;
    }
    GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length);
    call_read_cb(exec_ctx, tcp, 1);
    TCP_UNREF(exec_ctx, tcp, "read");
  }

  GPR_TIMER_END("tcp_continue_read", 0);
}