Example #1
0
/* Asynchronous callback from the IOCP, or the background thread. */
static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, bool success) {
  grpc_tcp *tcp = tcpp;
  grpc_closure *cb = tcp->read_cb;
  grpc_winsocket *socket = tcp->socket;
  gpr_slice sub;
  grpc_winsocket_callback_info *info = &socket->read_info;

  if (success) {
    if (socket->read_info.wsa_error != 0 && !tcp->shutting_down) {
      if (socket->read_info.wsa_error != WSAECONNRESET) {
        char *utf8_message = gpr_format_message(info->wsa_error);
        gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
        gpr_free(utf8_message);
      }
      success = 0;
      gpr_slice_unref(tcp->read_slice);
    } else {
      if (info->bytes_transfered != 0 && !tcp->shutting_down) {
        sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered);
        gpr_slice_buffer_add(tcp->read_slices, sub);
        success = 1;
      } else {
        gpr_slice_unref(tcp->read_slice);
        success = 0;
      }
    }
  }

  tcp->read_cb = NULL;
  TCP_UNREF(tcp, "read");
  if (cb) {
    cb->cb(exec_ctx, cb->cb_arg, success);
  }
}
Example #2
0
/* Asynchronous callback from the IOCP, or the background thread. */
static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) {
  grpc_tcp *tcp = tcpp;
  grpc_closure *cb = tcp->read_cb;
  grpc_winsocket *socket = tcp->socket;
  gpr_slice sub;
  grpc_winsocket_callback_info *info = &socket->read_info;

  GRPC_ERROR_REF(error);

  if (error == GRPC_ERROR_NONE) {
    if (info->wsa_error != 0 && !tcp->shutting_down) {
      char *utf8_message = gpr_format_message(info->wsa_error);
      error = GRPC_ERROR_CREATE(utf8_message);
      gpr_free(utf8_message);
      gpr_slice_unref(tcp->read_slice);
    } else {
      if (info->bytes_transfered != 0 && !tcp->shutting_down) {
        sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered);
        gpr_slice_buffer_add(tcp->read_slices, sub);
      } else {
        gpr_slice_unref(tcp->read_slice);
        error = GRPC_ERROR_CREATE("End of TCP stream");
      }
    }
  }

  tcp->read_cb = NULL;
  TCP_UNREF(tcp, "read");
  grpc_exec_ctx_sched(exec_ctx, cb, error, NULL);
}
Example #3
0
/* Asynchronous callback from the IOCP, or the background thread. */
static void on_read(void *tcpp, int from_iocp) {
  grpc_tcp *tcp = (grpc_tcp *) tcpp;
  grpc_winsocket *socket = tcp->socket;
  gpr_slice sub;
  gpr_slice *slice = NULL;
  size_t nslices = 0;
  grpc_endpoint_cb_status status;
  grpc_endpoint_read_cb cb;
  grpc_winsocket_callback_info *info = &socket->read_info;
  void *opaque = tcp->read_user_data;
  int do_abort = 0;

  gpr_mu_lock(&tcp->mu);
  cb = tcp->read_cb;
  tcp->read_cb = NULL;
  if (!from_iocp || tcp->shutting_down) {
    /* If we are here with from_iocp set to true, it means we got raced to
    shutting down the endpoint. No actual abort callback will happen
    though, so we're going to do it from here. */
    do_abort = 1;
  }
  gpr_mu_unlock(&tcp->mu);

  if (do_abort) {
    if (from_iocp) {
      tcp->socket->read_info.outstanding = 0;
      gpr_slice_unref(tcp->read_slice);
    }
    tcp_unref(tcp);
    if (cb) cb(opaque, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN);
    return;
  }

  GPR_ASSERT(tcp->socket->read_info.outstanding);

  if (socket->read_info.wsa_error != 0) {
    if (socket->read_info.wsa_error != WSAECONNRESET) {
      char *utf8_message = gpr_format_message(info->wsa_error);
      gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
      gpr_free(utf8_message);
    }
    status = GRPC_ENDPOINT_CB_ERROR;
  } else {
    if (info->bytes_transfered != 0) {
      sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered);
      status = GRPC_ENDPOINT_CB_OK;
      slice = ⊂
      nslices = 1;
    } else {
      gpr_slice_unref(tcp->read_slice);
      status = GRPC_ENDPOINT_CB_EOF;
    }
  }

  tcp->socket->read_info.outstanding = 0;

  tcp_unref(tcp);
  cb(opaque, slice, nslices, status);
}
Example #4
0
/* Asynchronous callback from the IOCP, or the background thread. */
static int on_read(grpc_tcp *tcp, int from_iocp) {
  grpc_winsocket *socket = tcp->socket;
  gpr_slice sub;
  gpr_slice *slice = NULL;
  size_t nslices = 0;
  int success;
  grpc_winsocket_callback_info *info = &socket->read_info;
  int do_abort = 0;

  gpr_mu_lock(&tcp->mu);
  if (!from_iocp || tcp->shutting_down) {
    /* If we are here with from_iocp set to true, it means we got raced to
    shutting down the endpoint. No actual abort callback will happen
    though, so we're going to do it from here. */
    do_abort = 1;
  }
  gpr_mu_unlock(&tcp->mu);

  if (do_abort) {
    if (from_iocp) {
      tcp->socket->read_info.outstanding = 0;
      gpr_slice_unref(tcp->read_slice);
    }
    return 0;
  }

  GPR_ASSERT(tcp->socket->read_info.outstanding);

  if (socket->read_info.wsa_error != 0) {
    if (socket->read_info.wsa_error != WSAECONNRESET) {
      char *utf8_message = gpr_format_message(info->wsa_error);
      gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
      gpr_free(utf8_message);
    }
    success = 0;
    gpr_slice_unref(tcp->read_slice);
  } else {
    if (info->bytes_transfered != 0) {
      sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered);
      gpr_slice_buffer_add(tcp->read_slices, sub);
      success = 1;
    } else {
      gpr_slice_unref(tcp->read_slice);
      success = 0;
    }
  }

  tcp->socket->read_info.outstanding = 0;

  return success;
}
Example #5
0
gpr_slice gpr_slice_sub(gpr_slice source, size_t begin, size_t end) {
  gpr_slice subset;

  if (end - begin <= sizeof(subset.data.inlined.bytes)) {
    subset.refcount = NULL;
    subset.data.inlined.length = (gpr_uint8)(end - begin);
    memcpy(subset.data.inlined.bytes, GPR_SLICE_START_PTR(source) + begin,
           end - begin);
  } else {
    subset = gpr_slice_sub_no_ref(source, begin, end);
    /* Bump the refcount */
    subset.refcount->ref(subset.refcount);
  }
  return subset;
}
grpc_error *grpc_chttp2_perform_read(
    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
    gpr_slice slice) {
  uint8_t *beg = GPR_SLICE_START_PTR(slice);
  uint8_t *end = GPR_SLICE_END_PTR(slice);
  uint8_t *cur = beg;
  grpc_error *err;

  if (cur == end) return GRPC_ERROR_NONE;

  switch (transport_parsing->deframe_state) {
    case GRPC_DTS_CLIENT_PREFIX_0:
    case GRPC_DTS_CLIENT_PREFIX_1:
    case GRPC_DTS_CLIENT_PREFIX_2:
    case GRPC_DTS_CLIENT_PREFIX_3:
    case GRPC_DTS_CLIENT_PREFIX_4:
    case GRPC_DTS_CLIENT_PREFIX_5:
    case GRPC_DTS_CLIENT_PREFIX_6:
    case GRPC_DTS_CLIENT_PREFIX_7:
    case GRPC_DTS_CLIENT_PREFIX_8:
    case GRPC_DTS_CLIENT_PREFIX_9:
    case GRPC_DTS_CLIENT_PREFIX_10:
    case GRPC_DTS_CLIENT_PREFIX_11:
    case GRPC_DTS_CLIENT_PREFIX_12:
    case GRPC_DTS_CLIENT_PREFIX_13:
    case GRPC_DTS_CLIENT_PREFIX_14:
    case GRPC_DTS_CLIENT_PREFIX_15:
    case GRPC_DTS_CLIENT_PREFIX_16:
    case GRPC_DTS_CLIENT_PREFIX_17:
    case GRPC_DTS_CLIENT_PREFIX_18:
    case GRPC_DTS_CLIENT_PREFIX_19:
    case GRPC_DTS_CLIENT_PREFIX_20:
    case GRPC_DTS_CLIENT_PREFIX_21:
    case GRPC_DTS_CLIENT_PREFIX_22:
    case GRPC_DTS_CLIENT_PREFIX_23:
      while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
        if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
                                                          ->deframe_state]) {
          char *msg;
          gpr_asprintf(
              &msg,
              "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
              "at byte %d",
              GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
                                                    ->deframe_state],
              (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
                  [transport_parsing->deframe_state],
              *cur, (int)*cur, transport_parsing->deframe_state);
          err = GRPC_ERROR_CREATE(msg);
          gpr_free(msg);
          return err;
        }
        ++cur;
        ++transport_parsing->deframe_state;
      }
      if (cur == end) {
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    dts_fh_0:
    case GRPC_DTS_FH_0:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16;
      if (++cur == end) {
        transport_parsing->deframe_state = GRPC_DTS_FH_1;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_1:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8;
      if (++cur == end) {
        transport_parsing->deframe_state = GRPC_DTS_FH_2;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_2:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_frame_size |= *cur;
      if (++cur == end) {
        transport_parsing->deframe_state = GRPC_DTS_FH_3;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_3:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_frame_type = *cur;
      if (++cur == end) {
        transport_parsing->deframe_state = GRPC_DTS_FH_4;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_4:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_frame_flags = *cur;
      if (++cur == end) {
        transport_parsing->deframe_state = GRPC_DTS_FH_5;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_5:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
      if (++cur == end) {
        transport_parsing->deframe_state = GRPC_DTS_FH_6;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_6:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16;
      if (++cur == end) {
        transport_parsing->deframe_state = GRPC_DTS_FH_7;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_7:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8;
      if (++cur == end) {
        transport_parsing->deframe_state = GRPC_DTS_FH_8;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_8:
      GPR_ASSERT(cur < end);
      transport_parsing->incoming_stream_id |= ((uint32_t)*cur);
      transport_parsing->deframe_state = GRPC_DTS_FRAME;
      err = init_frame_parser(exec_ctx, transport_parsing);
      if (err != GRPC_ERROR_NONE) {
        return err;
      }
      if (transport_parsing->incoming_stream_id != 0 &&
          transport_parsing->incoming_stream_id >
              transport_parsing->last_incoming_stream_id) {
        transport_parsing->last_incoming_stream_id =
            transport_parsing->incoming_stream_id;
      }
      if (transport_parsing->incoming_frame_size == 0) {
        err = parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
                                1);
        if (err != GRPC_ERROR_NONE) {
          return err;
        }
        transport_parsing->incoming_stream = NULL;
        if (++cur == end) {
          transport_parsing->deframe_state = GRPC_DTS_FH_0;
          return GRPC_ERROR_NONE;
        }
        goto dts_fh_0; /* loop */
      } else if (transport_parsing->incoming_frame_size >
                 transport_parsing->max_frame_size) {
        char *msg;
        gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d",
                     transport_parsing->incoming_frame_size,
                     transport_parsing->max_frame_size);
        err = GRPC_ERROR_CREATE(msg);
        gpr_free(msg);
        return err;
      }
      if (++cur == end) {
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FRAME:
      GPR_ASSERT(cur < end);
      if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) {
        err = parse_frame_slice(exec_ctx, transport_parsing,
                                gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
                                                     (size_t)(end - beg)),
                                1);
        if (err != GRPC_ERROR_NONE) {
          return err;
        }
        transport_parsing->deframe_state = GRPC_DTS_FH_0;
        transport_parsing->incoming_stream = NULL;
        return GRPC_ERROR_NONE;
      } else if ((uint32_t)(end - cur) >
                 transport_parsing->incoming_frame_size) {
        size_t cur_offset = (size_t)(cur - beg);
        err = parse_frame_slice(
            exec_ctx, transport_parsing,
            gpr_slice_sub_no_ref(
                slice, cur_offset,
                cur_offset + transport_parsing->incoming_frame_size),
            1);
        if (err != GRPC_ERROR_NONE) {
          return err;
        }
        cur += transport_parsing->incoming_frame_size;
        transport_parsing->incoming_stream = NULL;
        goto dts_fh_0; /* loop */
      } else {
        err = parse_frame_slice(exec_ctx, transport_parsing,
                                gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
                                                     (size_t)(end - beg)),
                                0);
        if (err != GRPC_ERROR_NONE) {
          return err;
        }
        transport_parsing->incoming_frame_size -= (uint32_t)(end - cur);
        return GRPC_ERROR_NONE;
      }
      GPR_UNREACHABLE_CODE(return 0);
  }

  GPR_UNREACHABLE_CODE(return 0);
}
Example #7
0
int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
                             gpr_slice slice) {
    gpr_uint8 *beg = GPR_SLICE_START_PTR(slice);
    gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
    gpr_uint8 *cur = beg;

    if (cur == end) return 1;

    switch (transport_parsing->deframe_state) {
    case GRPC_DTS_CLIENT_PREFIX_0:
    case GRPC_DTS_CLIENT_PREFIX_1:
    case GRPC_DTS_CLIENT_PREFIX_2:
    case GRPC_DTS_CLIENT_PREFIX_3:
    case GRPC_DTS_CLIENT_PREFIX_4:
    case GRPC_DTS_CLIENT_PREFIX_5:
    case GRPC_DTS_CLIENT_PREFIX_6:
    case GRPC_DTS_CLIENT_PREFIX_7:
    case GRPC_DTS_CLIENT_PREFIX_8:
    case GRPC_DTS_CLIENT_PREFIX_9:
    case GRPC_DTS_CLIENT_PREFIX_10:
    case GRPC_DTS_CLIENT_PREFIX_11:
    case GRPC_DTS_CLIENT_PREFIX_12:
    case GRPC_DTS_CLIENT_PREFIX_13:
    case GRPC_DTS_CLIENT_PREFIX_14:
    case GRPC_DTS_CLIENT_PREFIX_15:
    case GRPC_DTS_CLIENT_PREFIX_16:
    case GRPC_DTS_CLIENT_PREFIX_17:
    case GRPC_DTS_CLIENT_PREFIX_18:
    case GRPC_DTS_CLIENT_PREFIX_19:
    case GRPC_DTS_CLIENT_PREFIX_20:
    case GRPC_DTS_CLIENT_PREFIX_21:
    case GRPC_DTS_CLIENT_PREFIX_22:
    case GRPC_DTS_CLIENT_PREFIX_23:
        while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
            if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
                    ->deframe_state]) {
                gpr_log(GPR_INFO,
                        "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
                        "at byte %d",
                        GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
                                ->deframe_state],
                        (int)(gpr_uint8)GRPC_CHTTP2_CLIENT_CONNECT_STRING
                        [transport_parsing->deframe_state],
                        *cur, (int)*cur, transport_parsing->deframe_state);
                return 0;
            }
            ++cur;
            ++transport_parsing->deframe_state;
        }
        if (cur == end) {
            return 1;
        }
        /* fallthrough */
dts_fh_0:
    case GRPC_DTS_FH_0:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_size = ((gpr_uint32)*cur) << 16;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_1;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_1:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_size |= ((gpr_uint32)*cur) << 8;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_2;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_2:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_size |= *cur;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_3;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_3:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_type = *cur;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_4;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_4:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_flags = *cur;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_5;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_5:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_stream_id = (((gpr_uint32)*cur) & 0x7f) << 24;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_6;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_6:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 16;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_7;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_7:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 8;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_8;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_8:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur);
        transport_parsing->deframe_state = GRPC_DTS_FRAME;
        if (!init_frame_parser(transport_parsing)) {
            return 0;
        }
        if (transport_parsing->incoming_stream_id) {
            transport_parsing->last_incoming_stream_id =
                transport_parsing->incoming_stream_id;
        }
        if (transport_parsing->incoming_frame_size == 0) {
            if (!parse_frame_slice(transport_parsing, gpr_empty_slice(), 1)) {
                return 0;
            }
            transport_parsing->incoming_stream = NULL;
            if (++cur == end) {
                transport_parsing->deframe_state = GRPC_DTS_FH_0;
                return 1;
            }
            goto dts_fh_0; /* loop */
        }
        if (++cur == end) {
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FRAME:
        GPR_ASSERT(cur < end);
        if ((gpr_uint32)(end - cur) == transport_parsing->incoming_frame_size) {
            if (!parse_frame_slice(
                        transport_parsing,
                        gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 1)) {
                return 0;
            }
            transport_parsing->deframe_state = GRPC_DTS_FH_0;
            transport_parsing->incoming_stream = NULL;
            return 1;
        } else if ((gpr_uint32)(end - cur) >
                   transport_parsing->incoming_frame_size) {
            if (!parse_frame_slice(
                        transport_parsing,
                        gpr_slice_sub_no_ref(
                            slice, cur - beg,
                            cur + transport_parsing->incoming_frame_size - beg),
                        1)) {
                return 0;
            }
            cur += transport_parsing->incoming_frame_size;
            transport_parsing->incoming_stream = NULL;
            goto dts_fh_0; /* loop */
        } else {
            if (!parse_frame_slice(
                        transport_parsing,
                        gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 0)) {
                return 0;
            }
            transport_parsing->incoming_frame_size -= (end - cur);
            return 1;
        }
        gpr_log(GPR_ERROR, "should never reach here");
        abort();
    }

    gpr_log(GPR_ERROR, "should never reach here");
    abort();

    return 0;
}