Example #1
0
int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
                            int32_t stream_id,
                            const nghttp2_priority_spec *pri_spec) {
  int rv;
  nghttp2_outbound_item *item;
  nghttp2_frame *frame;
  nghttp2_priority_spec copy_pri_spec;
  nghttp2_mem *mem;

  mem = &session->mem;

  if (stream_id == 0 || pri_spec == NULL) {
    return NGHTTP2_ERR_INVALID_ARGUMENT;
  }

  if (stream_id == pri_spec->stream_id) {
    return NGHTTP2_ERR_INVALID_ARGUMENT;
  }

  copy_pri_spec = *pri_spec;

  nghttp2_priority_spec_normalize_weight(&copy_pri_spec);

  item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));

  if (item == NULL) {
    return NGHTTP2_ERR_NOMEM;
  }

  nghttp2_outbound_item_init(item);

  frame = &item->frame;

  nghttp2_frame_priority_init(&frame->priority, stream_id, &copy_pri_spec);

  rv = nghttp2_session_add_item(session, item);

  if (rv != 0) {
    nghttp2_frame_priority_free(&frame->priority);
    nghttp2_mem_free(mem, item);

    return rv;
  }

  return 0;
}
Example #2
0
int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
                        int32_t stream_id,
                        const nghttp2_data_provider *data_prd) {
  int rv;
  nghttp2_outbound_item *item;
  nghttp2_frame *frame;
  nghttp2_data_aux_data *aux_data;
  uint8_t nflags = flags & NGHTTP2_FLAG_END_STREAM;
  nghttp2_mem *mem;

  mem = &session->mem;

  if (stream_id == 0) {
    return NGHTTP2_ERR_INVALID_ARGUMENT;
  }

  item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  if (item == NULL) {
    return NGHTTP2_ERR_NOMEM;
  }

  nghttp2_outbound_item_init(item);

  frame = &item->frame;
  aux_data = &item->aux_data.data;
  aux_data->data_prd = *data_prd;
  aux_data->eof = 0;
  aux_data->flags = nflags;

  /* flags are sent on transmission */
  nghttp2_frame_data_init(&frame->data, NGHTTP2_FLAG_NONE, stream_id);

  rv = nghttp2_session_add_item(session, item);
  if (rv != 0) {
    nghttp2_frame_data_free(&frame->data);
    nghttp2_mem_free(mem, item);
    return rv;
  }
  return 0;
}
Example #3
0
int nghttp2_submit_extension(nghttp2_session *session, uint8_t type,
                             uint8_t flags, int32_t stream_id, void *payload) {
  int rv;
  nghttp2_outbound_item *item;
  nghttp2_frame *frame;
  nghttp2_mem *mem;

  mem = &session->mem;

  if (type <= NGHTTP2_CONTINUATION) {
    return NGHTTP2_ERR_INVALID_ARGUMENT;
  }

  if (!session->callbacks.pack_extension_callback) {
    return NGHTTP2_ERR_INVALID_STATE;
  }

  item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  if (item == NULL) {
    return NGHTTP2_ERR_NOMEM;
  }

  nghttp2_outbound_item_init(item);

  frame = &item->frame;
  nghttp2_frame_extension_init(&frame->ext, type, flags, stream_id, payload);

  rv = nghttp2_session_add_item(session, item);
  if (rv != 0) {
    nghttp2_frame_extension_free(&frame->ext);
    nghttp2_mem_free(mem, item);
    return rv;
  }

  return 0;
}
Example #4
0
/* This function takes ownership of |nva_copy|. Regardless of the
   return value, the caller must not free |nva_copy| after this
   function returns. */
static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
                                     int32_t stream_id,
                                     const nghttp2_priority_spec *pri_spec,
                                     nghttp2_nv *nva_copy, size_t nvlen,
                                     const nghttp2_data_provider *data_prd,
                                     void *stream_user_data) {
  int rv;
  uint8_t flags_copy;
  nghttp2_outbound_item *item = NULL;
  nghttp2_frame *frame = NULL;
  nghttp2_headers_category hcat;
  nghttp2_mem *mem;

  mem = &session->mem;

  if (stream_id == 0) {
    rv = NGHTTP2_ERR_INVALID_ARGUMENT;
    goto fail;
  }

  if (stream_id == -1) {
    if ((int32_t)session->next_stream_id == pri_spec->stream_id) {
      rv = NGHTTP2_ERR_INVALID_ARGUMENT;
      goto fail;
    }
  } else if (stream_id == pri_spec->stream_id) {
    rv = NGHTTP2_ERR_INVALID_ARGUMENT;
    goto fail;
  }

  item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  if (item == NULL) {
    rv = NGHTTP2_ERR_NOMEM;
    goto fail;
  }

  nghttp2_outbound_item_init(item);

  if (data_prd != NULL && data_prd->read_callback != NULL) {
    item->aux_data.headers.data_prd = *data_prd;
  }

  item->aux_data.headers.stream_user_data = stream_user_data;

  flags_copy =
      (uint8_t)((flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
                NGHTTP2_FLAG_END_HEADERS);

  if (stream_id == -1) {
    if (session->next_stream_id > INT32_MAX) {
      rv = NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
      goto fail;
    }

    stream_id = (int32_t)session->next_stream_id;
    session->next_stream_id += 2;

    hcat = NGHTTP2_HCAT_REQUEST;
  } else {
    /* More specific categorization will be done later. */
    hcat = NGHTTP2_HCAT_HEADERS;
  }

  frame = &item->frame;

  nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat,
                             pri_spec, nva_copy, nvlen);

  rv = nghttp2_session_add_item(session, item);

  if (rv != 0) {
    nghttp2_frame_headers_free(&frame->headers, mem);
    goto fail2;
  }

  if (hcat == NGHTTP2_HCAT_REQUEST) {
    return stream_id;
  }

  return 0;

fail:
  /* nghttp2_frame_headers_init() takes ownership of nva_copy. */
  nghttp2_nv_array_del(nva_copy, mem);
fail2:
  nghttp2_mem_free(mem, item);

  return rv;
}
Example #5
0
int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
                                    int32_t stream_id, const nghttp2_nv *nva,
                                    size_t nvlen,
                                    void *promised_stream_user_data) {
  nghttp2_outbound_item *item;
  nghttp2_frame *frame;
  nghttp2_nv *nva_copy;
  uint8_t flags_copy;
  int32_t promised_stream_id;
  int rv;
  nghttp2_mem *mem;

  mem = &session->mem;

  if (stream_id == 0 || nghttp2_session_is_my_stream_id(session, stream_id)) {
    return NGHTTP2_ERR_INVALID_ARGUMENT;
  }

  if (!session->server) {
    return NGHTTP2_ERR_PROTO;
  }

  /* All 32bit signed stream IDs are spent. */
  if (session->next_stream_id > INT32_MAX) {
    return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
  }

  item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  if (item == NULL) {
    return NGHTTP2_ERR_NOMEM;
  }

  nghttp2_outbound_item_init(item);

  item->aux_data.headers.stream_user_data = promised_stream_user_data;

  frame = &item->frame;

  rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem);
  if (rv < 0) {
    nghttp2_mem_free(mem, item);
    return rv;
  }

  flags_copy = NGHTTP2_FLAG_END_HEADERS;

  promised_stream_id = (int32_t)session->next_stream_id;
  session->next_stream_id += 2;

  nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy, stream_id,
                                  promised_stream_id, nva_copy, nvlen);

  rv = nghttp2_session_add_item(session, item);

  if (rv != 0) {
    nghttp2_frame_push_promise_free(&frame->push_promise, mem);
    nghttp2_mem_free(mem, item);

    return rv;
  }

  return promised_stream_id;
}
Example #6
0
int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
                          int32_t stream_id, const uint8_t *origin,
                          size_t origin_len, const uint8_t *field_value,
                          size_t field_value_len) {
  nghttp2_mem *mem;
  uint8_t *buf, *p;
  uint8_t *origin_copy;
  uint8_t *field_value_copy;
  nghttp2_outbound_item *item;
  nghttp2_frame *frame;
  nghttp2_ext_altsvc *altsvc;
  int rv;

  mem = &session->mem;

  if (!session->server) {
    return NGHTTP2_ERR_INVALID_STATE;
  }

  if (2 + origin_len + field_value_len > NGHTTP2_MAX_PAYLOADLEN) {
    return NGHTTP2_ERR_INVALID_ARGUMENT;
  }

  if (stream_id == 0) {
    if (origin_len == 0) {
      return NGHTTP2_ERR_INVALID_ARGUMENT;
    }
  } else if (origin_len != 0) {
    return NGHTTP2_ERR_INVALID_ARGUMENT;
  }

  buf = nghttp2_mem_malloc(mem, origin_len + field_value_len + 2);
  if (buf == NULL) {
    return NGHTTP2_ERR_NOMEM;
  }

  p = buf;

  origin_copy = p;
  if (origin_len) {
    p = nghttp2_cpymem(p, origin, origin_len);
  }
  *p++ = '\0';

  field_value_copy = p;
  if (field_value_len) {
    p = nghttp2_cpymem(p, field_value, field_value_len);
  }
  *p++ = '\0';

  item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  if (item == NULL) {
    rv = NGHTTP2_ERR_NOMEM;
    goto fail_item_malloc;
  }

  nghttp2_outbound_item_init(item);

  item->aux_data.ext.builtin = 1;

  altsvc = &item->ext_frame_payload.altsvc;

  frame = &item->frame;
  frame->ext.payload = altsvc;

  nghttp2_frame_altsvc_init(&frame->ext, stream_id, origin_copy, origin_len,
                            field_value_copy, field_value_len);

  rv = nghttp2_session_add_item(session, item);
  if (rv != 0) {
    nghttp2_frame_altsvc_free(&frame->ext, mem);
    nghttp2_mem_free(mem, item);

    return rv;
  }

  return 0;

fail_item_malloc:
  free(buf);

  return rv;
}