示例#1
0
static gpr_slice compute_default_pem_root_certs_once(void) {
  gpr_slice result = gpr_empty_slice();

  /* First try to load the roots from the environment. */
  char *default_root_certs_path =
      gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
  if (default_root_certs_path != NULL) {
    result = gpr_load_file(default_root_certs_path, 0, NULL);
    gpr_free(default_root_certs_path);
  }

  /* Try overridden roots if needed. */
  grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL;
  if (GPR_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) {
    char *pem_root_certs = NULL;
    ovrd_res = ssl_roots_override_cb(&pem_root_certs);
    if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) {
      GPR_ASSERT(pem_root_certs != NULL);
      result = gpr_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free);
    }
  }

  /* Fall back to installed certs if needed. */
  if (GPR_SLICE_IS_EMPTY(result) &&
      ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) {
    result = gpr_load_file(installed_roots_path, 0, NULL);
  }
  return result;
}
示例#2
0
static void init_default_pem_root_certs(void) {
  /* First try to load the roots from the environment. */
  char *default_root_certs_path =
      gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
  if (default_root_certs_path == NULL) {
    default_pem_root_certs = gpr_empty_slice();
  } else {
    default_pem_root_certs = gpr_load_file(default_root_certs_path, 0, NULL);
    gpr_free(default_root_certs_path);
  }

  /* Fall back to installed certs if needed. */
  if (GPR_SLICE_IS_EMPTY(default_pem_root_certs)) {
    default_pem_root_certs = gpr_load_file(installed_roots_path, 0, NULL);
  }
}
示例#3
0
文件: file.c 项目: AlexTalks/bazel
gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
                        int *success) {
  unsigned char *contents = NULL;
  size_t contents_size = 0;
  char *error_msg = NULL;
  gpr_slice result = gpr_empty_slice();
  FILE *file;
  size_t bytes_read = 0;

  GRPC_SCHEDULING_START_BLOCKING_REGION;
  file = fopen(filename, "rb");
  if (file == NULL) {
    gpr_asprintf(&error_msg, "Could not open file %s (error = %s).", filename,
                 strerror(errno));
    GPR_ASSERT(error_msg != NULL);
    goto end;
  }
  fseek(file, 0, SEEK_END);
  /* Converting to size_t on the assumption that it will not fail */
  contents_size = (size_t)ftell(file);
  fseek(file, 0, SEEK_SET);
  contents = gpr_malloc(contents_size + (add_null_terminator ? 1 : 0));
  bytes_read = fread(contents, 1, contents_size, file);
  if (bytes_read < contents_size) {
    GPR_ASSERT(ferror(file));
    gpr_asprintf(&error_msg, "Error %s occured while reading file %s.",
                 strerror(errno), filename);
    GPR_ASSERT(error_msg != NULL);
    goto end;
  }
  if (success != NULL) *success = 1;
  if (add_null_terminator) {
    contents[contents_size++] = 0;
  }
  result = gpr_slice_new(contents, contents_size, gpr_free);

end:
  if (error_msg != NULL) {
    gpr_log(GPR_ERROR, "%s", error_msg);
    gpr_free(error_msg);
    if (success != NULL) *success = 0;
  }
  if (file != NULL) fclose(file);
  GRPC_SCHEDULING_END_BLOCKING_REGION;
  return result;
}
示例#4
0
文件: load_file.c 项目: Indifer/grpc
grpc_error *grpc_load_file(const char *filename, int add_null_terminator,
                           grpc_slice *output) {
  unsigned char *contents = NULL;
  size_t contents_size = 0;
  grpc_slice result = gpr_empty_slice();
  FILE *file;
  size_t bytes_read = 0;
  grpc_error *error = GRPC_ERROR_NONE;

  GRPC_SCHEDULING_START_BLOCKING_REGION;
  file = fopen(filename, "rb");
  if (file == NULL) {
    error = GRPC_OS_ERROR(errno, "fopen");
    goto end;
  }
  fseek(file, 0, SEEK_END);
  /* Converting to size_t on the assumption that it will not fail */
  contents_size = (size_t)ftell(file);
  fseek(file, 0, SEEK_SET);
  contents = gpr_malloc(contents_size + (add_null_terminator ? 1 : 0));
  bytes_read = fread(contents, 1, contents_size, file);
  if (bytes_read < contents_size) {
    error = GRPC_OS_ERROR(errno, "fread");
    GPR_ASSERT(ferror(file));
    goto end;
  }
  if (add_null_terminator) {
    contents[contents_size++] = 0;
  }
  result = grpc_slice_new(contents, contents_size, gpr_free);

end:
  *output = result;
  if (file != NULL) fclose(file);
  if (error != GRPC_ERROR_NONE) {
    grpc_error *error_out = grpc_error_set_str(
        GRPC_ERROR_CREATE_REFERENCING("Failed to load file", &error, 1),
        GRPC_ERROR_STR_FILENAME, filename);
    GRPC_ERROR_UNREF(error);
    error = error_out;
  }
  GRPC_SCHEDULING_END_BLOCKING_REGION;
  return error;
}
/* Takes ownership of creds_path if not NULL. */
static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
  grpc_json *json = NULL;
  grpc_auth_json_key key;
  grpc_auth_refresh_token token;
  grpc_call_credentials *result = NULL;
  gpr_slice creds_data = gpr_empty_slice();
  int file_ok = 0;
  if (creds_path == NULL) goto end;
  creds_data = gpr_load_file(creds_path, 0, &file_ok);
  if (!file_ok) goto end;
  json = grpc_json_parse_string_with_len(
      (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
  if (json == NULL) goto end;

  /* First, try an auth json key. */
  key = grpc_auth_json_key_create_from_json(json);
  if (grpc_auth_json_key_is_valid(&key)) {
    result =
        grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
            key, grpc_max_auth_token_lifetime());
    goto end;
  }

  /* Then try a refresh token if the auth json key was invalid. */
  token = grpc_auth_refresh_token_create_from_json(json);
  if (grpc_auth_refresh_token_is_valid(&token)) {
    result =
        grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
    goto end;
  }

end:
  if (creds_path != NULL) gpr_free(creds_path);
  gpr_slice_unref(creds_data);
  if (json != NULL) grpc_json_destroy(json);
  return result;
}
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);
}
void grpc_chttp2_publish_reads(
    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
    grpc_chttp2_transport_parsing *transport_parsing) {
  grpc_chttp2_stream_global *stream_global;
  grpc_chttp2_stream_parsing *stream_parsing;
  int was_zero;
  int is_zero;

  /* transport_parsing->last_incoming_stream_id is used as
     last-grpc_chttp2_stream-id when
     sending GOAWAY frame.
     https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
     says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
     ID.  So,
     since we don't have server pushed streams, client should send
     GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
  if (!transport_parsing->is_client) {
    transport_global->last_incoming_stream_id =
        transport_parsing->last_incoming_stream_id;
  }

  /* update global settings */
  if (transport_parsing->settings_updated) {
    memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
           transport_parsing->settings, sizeof(transport_parsing->settings));
    transport_parsing->settings_updated = 0;
  }

  /* update settings based on ack if received */
  if (transport_parsing->settings_ack_received) {
    memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
           transport_global->settings[GRPC_SENT_SETTINGS],
           GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
    transport_parsing->settings_ack_received = 0;
    transport_global->sent_local_settings = 0;
  }

  /* move goaway to the global state if we received one (it will be
     published later */
  if (transport_parsing->goaway_received) {
    grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global,
                                    (uint32_t)transport_parsing->goaway_error,
                                    transport_parsing->goaway_text);
    transport_parsing->goaway_text = gpr_empty_slice();
    transport_parsing->goaway_received = 0;
  }

  /* propagate flow control tokens to global state */
  was_zero = transport_global->outgoing_window <= 0;
  GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window,
                                  transport_parsing, outgoing_window);
  is_zero = transport_global->outgoing_window <= 0;
  if (was_zero && !is_zero) {
    while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
                                                     &stream_global)) {
      grpc_chttp2_become_writable(transport_global, stream_global);
    }
  }

  if (transport_parsing->incoming_window <
      transport_global->connection_window_target * 3 / 4) {
    int64_t announce_bytes = transport_global->connection_window_target -
                             transport_parsing->incoming_window;
    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global,
                                      announce_incoming_window, announce_bytes);
    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing,
                                      incoming_window, announce_bytes);
  }

  /* for each stream that saw an update, fixup global state */
  while (grpc_chttp2_list_pop_parsing_seen_stream(
      transport_global, transport_parsing, &stream_global, &stream_parsing)) {
    if (stream_parsing->seen_error) {
      stream_global->seen_error = true;
      stream_global->exceeded_metadata_size =
          stream_parsing->exceeded_metadata_size;
      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
    }

    /* flush stats to global stream state */
    grpc_transport_move_stats(&stream_parsing->stats, &stream_global->stats);

    /* update outgoing flow control window */
    was_zero = stream_global->outgoing_window <= 0;
    GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global,
                                 outgoing_window, stream_parsing,
                                 outgoing_window);
    is_zero = stream_global->outgoing_window <= 0;
    if (was_zero && !is_zero) {
      grpc_chttp2_become_writable(transport_global, stream_global);
    }

    stream_global->max_recv_bytes -= (uint32_t)GPR_MIN(
        stream_global->max_recv_bytes, stream_parsing->received_bytes);
    stream_parsing->received_bytes = 0;

    /* publish incoming stream ops */
    if (stream_global->incoming_frames.tail != NULL) {
      stream_global->incoming_frames.tail->is_tail = 0;
    }
    if (stream_parsing->data_parser.incoming_frames.head != NULL) {
      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
    }
    grpc_chttp2_incoming_frame_queue_merge(
        &stream_global->incoming_frames,
        &stream_parsing->data_parser.incoming_frames);
    if (stream_global->incoming_frames.tail != NULL) {
      stream_global->incoming_frames.tail->is_tail = 1;
    }

    if (!stream_global->published_initial_metadata &&
        stream_parsing->got_metadata_on_parse[0]) {
      stream_parsing->got_metadata_on_parse[0] = 0;
      stream_global->published_initial_metadata = 1;
      GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
               stream_parsing->metadata_buffer[0],
               stream_global->received_initial_metadata);
      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
    }
    if (!stream_global->published_trailing_metadata &&
        stream_parsing->got_metadata_on_parse[1]) {
      stream_parsing->got_metadata_on_parse[1] = 0;
      stream_global->published_trailing_metadata = 1;
      GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
               stream_parsing->metadata_buffer[1],
               stream_global->received_trailing_metadata);
      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
    }

    if (stream_parsing->forced_close_error != GRPC_ERROR_NONE) {
      intptr_t reason;
      bool has_reason = grpc_error_get_int(stream_parsing->forced_close_error,
                                           GRPC_ERROR_INT_HTTP2_ERROR, &reason);
      if (has_reason && reason != GRPC_CHTTP2_NO_ERROR) {
        grpc_status_code status_code =
            has_reason
                ? grpc_chttp2_http2_error_to_grpc_status(
                      (grpc_chttp2_error_code)reason, stream_global->deadline)
                : GRPC_STATUS_INTERNAL;
        const char *status_details =
            grpc_error_string(stream_parsing->forced_close_error);
        gpr_slice slice_details = gpr_slice_from_copied_string(status_details);
        grpc_error_free_string(status_details);
        grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
                                status_code, &slice_details);
      }
      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
                                     1, 1, stream_parsing->forced_close_error);
    }

    if (stream_parsing->received_close) {
      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
                                     1, 0, GRPC_ERROR_NONE);
    }
  }
}
示例#8
0
文件: parsing.c 项目: xincun/grpc
void grpc_chttp2_publish_reads(
    grpc_chttp2_transport_global *transport_global,
    grpc_chttp2_transport_parsing *transport_parsing) {
    grpc_chttp2_stream_global *stream_global;
    grpc_chttp2_stream_parsing *stream_parsing;

    /* transport_parsing->last_incoming_stream_id is used as
       last-grpc_chttp2_stream-id when
       sending GOAWAY frame.
       https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
       says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
       ID.  So,
       since we don't have server pushed streams, client should send
       GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
    if (!transport_parsing->is_client) {
        transport_global->last_incoming_stream_id =
            transport_parsing->incoming_stream_id;
    }

    /* copy parsing qbuf to global qbuf */
    gpr_slice_buffer_move_into(&transport_parsing->qbuf, &transport_global->qbuf);

    /* update global settings */
    if (transport_parsing->settings_updated) {
        memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
               transport_parsing->settings, sizeof(transport_parsing->settings));
        transport_parsing->settings_updated = 0;
    }

    /* update settings based on ack if received */
    if (transport_parsing->settings_ack_received) {
        memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
               transport_global->settings[GRPC_SENT_SETTINGS],
               GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
        transport_parsing->settings_ack_received = 0;
    }

    /* move goaway to the global state if we received one (it will be
       published later */
    if (transport_parsing->goaway_received) {
        grpc_chttp2_add_incoming_goaway(transport_global,
                                        transport_parsing->goaway_error,
                                        transport_parsing->goaway_text);
        transport_parsing->goaway_text = gpr_empty_slice();
        transport_parsing->goaway_received = 0;
    }

    /* propagate flow control tokens to global state */
    if (transport_parsing->outgoing_window_update) {
        GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
            "parsed", transport_global, outgoing_window,
            transport_parsing->outgoing_window_update);
        GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
            "parsed", transport_parsing, outgoing_window_update,
            -(gpr_int64)transport_parsing->outgoing_window_update);
        transport_global->outgoing_window +=
            transport_parsing->outgoing_window_update;
        transport_parsing->outgoing_window_update = 0;
    }

    if (transport_parsing->incoming_window_delta) {
        GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
            "parsed", transport_global, incoming_window,
            -(gpr_int64)transport_parsing->incoming_window_delta);
        GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
            "parsed", transport_parsing, incoming_window_delta,
            -(gpr_int64)transport_parsing->incoming_window_delta);
        transport_global->incoming_window -=
            transport_parsing->incoming_window_delta;
        transport_parsing->incoming_window_delta = 0;
    }

    /* for each stream that saw an update, fixup global state */
    while (grpc_chttp2_list_pop_parsing_seen_stream(
                transport_global, transport_parsing, &stream_global, &stream_parsing)) {
        /* update incoming flow control window */
        if (stream_parsing->incoming_window_delta) {
            GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
                "parsed", transport_parsing, stream_global, incoming_window,
                -(gpr_int64)stream_parsing->incoming_window_delta);
            GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
                "parsed", transport_parsing, stream_parsing, incoming_window_delta,
                -(gpr_int64)stream_parsing->incoming_window_delta);
            GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
                "parsed", transport_parsing, stream_global, max_recv_bytes,
                -(gpr_int64)stream_parsing->incoming_window_delta);
            stream_global->incoming_window -= stream_parsing->incoming_window_delta;
            GPR_ASSERT(stream_global->max_recv_bytes >=
                       stream_parsing->incoming_window_delta);
            stream_global->max_recv_bytes -=
                stream_parsing->incoming_window_delta;
            stream_parsing->incoming_window_delta = 0;
            grpc_chttp2_list_add_writable_window_update_stream(transport_global,
                    stream_global);
        }

        /* update outgoing flow control window */
        if (stream_parsing->outgoing_window_update) {
            int was_zero = stream_global->outgoing_window <= 0;
            int is_zero;
            GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("parsed", transport_parsing,
                                             stream_global, outgoing_window,
                                             stream_parsing->outgoing_window_update);
            GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
                "parsed", transport_parsing, stream_parsing, outgoing_window_update,
                -(gpr_int64)stream_parsing->outgoing_window_update);
            stream_global->outgoing_window += stream_parsing->outgoing_window_update;
            stream_parsing->outgoing_window_update = 0;
            is_zero = stream_global->outgoing_window <= 0;
            if (was_zero && !is_zero) {
                grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
            }
        }

        /* updating closed status */
        if (stream_parsing->received_close) {
            stream_global->read_closed = 1;
            grpc_chttp2_list_add_read_write_state_changed(transport_global,
                    stream_global);
        }
        if (stream_parsing->saw_rst_stream) {
            stream_global->cancelled = 1;
            stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status(
                                                  stream_parsing->rst_stream_reason);
            if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) {
                stream_global->published_cancelled = 1;
            }
            grpc_chttp2_list_add_read_write_state_changed(transport_global,
                    stream_global);
        }

        /* publish incoming stream ops */
        if (stream_parsing->data_parser.incoming_sopb.nops > 0) {
            grpc_incoming_metadata_buffer_move_to_referencing_sopb(
                &stream_parsing->incoming_metadata, &stream_global->incoming_metadata,
                &stream_parsing->data_parser.incoming_sopb);
            grpc_sopb_move_to(&stream_parsing->data_parser.incoming_sopb,
                              &stream_global->incoming_sopb);
            grpc_chttp2_list_add_read_write_state_changed(transport_global,
                    stream_global);
        }
    }
}
示例#9
0
文件: parsing.c 项目: xincun/grpc
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;
}
示例#10
0
/* Takes ownership of creds_path if not NULL. */
static grpc_error *create_default_creds_from_path(
    char *creds_path, grpc_call_credentials **creds) {
  grpc_json *json = NULL;
  grpc_auth_json_key key;
  grpc_auth_refresh_token token;
  grpc_call_credentials *result = NULL;
  gpr_slice creds_data = gpr_empty_slice();
  grpc_error *error = GRPC_ERROR_NONE;
  if (creds_path == NULL) {
    error = GRPC_ERROR_CREATE("creds_path unset");
    goto end;
  }
  error = grpc_load_file(creds_path, 0, &creds_data);
  if (error != GRPC_ERROR_NONE) {
    goto end;
  }
  json = grpc_json_parse_string_with_len(
      (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
  if (json == NULL) {
    char *dump = gpr_dump_slice(creds_data, GPR_DUMP_HEX | GPR_DUMP_ASCII);
    error = grpc_error_set_str(GRPC_ERROR_CREATE("Failed to parse JSON"),
                               GRPC_ERROR_STR_RAW_BYTES, dump);
    gpr_free(dump);
    goto end;
  }

  /* First, try an auth json key. */
  key = grpc_auth_json_key_create_from_json(json);
  if (grpc_auth_json_key_is_valid(&key)) {
    result =
        grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
            key, grpc_max_auth_token_lifetime());
    if (result == NULL) {
      error = GRPC_ERROR_CREATE(
          "grpc_service_account_jwt_access_credentials_create_from_auth_json_"
          "key failed");
    }
    goto end;
  }

  /* Then try a refresh token if the auth json key was invalid. */
  token = grpc_auth_refresh_token_create_from_json(json);
  if (grpc_auth_refresh_token_is_valid(&token)) {
    result =
        grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
    if (result == NULL) {
      error = GRPC_ERROR_CREATE(
          "grpc_refresh_token_credentials_create_from_auth_refresh_token "
          "failed");
    }
    goto end;
  }

end:
  GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1);
  if (creds_path != NULL) gpr_free(creds_path);
  gpr_slice_unref(creds_data);
  if (json != NULL) grpc_json_destroy(json);
  *creds = result;
  return error;
}