void nghttp2_outbound_item_free(nghttp2_outbound_item *item)
{
  if(item == NULL) {
    return;
  }
  if(item->frame_cat == NGHTTP2_CAT_CTRL) {
    nghttp2_frame *frame;
    frame = nghttp2_outbound_item_get_ctrl_frame(item);
    switch(frame->hd.type) {
    case NGHTTP2_HEADERS:
      nghttp2_frame_headers_free(&frame->headers);
      if(item->aux_data) {
        free(((nghttp2_headers_aux_data*)item->aux_data)->data_prd);
      }
      break;
    case NGHTTP2_PRIORITY:
      nghttp2_frame_priority_free(&frame->priority);
      break;
    case NGHTTP2_RST_STREAM:
      nghttp2_frame_rst_stream_free(&frame->rst_stream);
      break;
    case NGHTTP2_SETTINGS:
      nghttp2_frame_settings_free(&frame->settings);
      break;
    case NGHTTP2_PUSH_PROMISE:
      nghttp2_frame_push_promise_free(&frame->push_promise);
      break;
    case NGHTTP2_PING:
      nghttp2_frame_ping_free(&frame->ping);
      break;
    case NGHTTP2_GOAWAY:
      nghttp2_frame_goaway_free(&frame->goaway);
      break;
    case NGHTTP2_WINDOW_UPDATE:
      nghttp2_frame_window_update_free(&frame->window_update);
      break;
    case NGHTTP2_EXT_ALTSVC:
      nghttp2_frame_altsvc_free(&frame->ext);
      free(frame->ext.payload);
      break;
    }
  } else if(item->frame_cat == NGHTTP2_CAT_DATA) {
    nghttp2_private_data *data_frame;
    data_frame = nghttp2_outbound_item_get_data_frame(item);
    nghttp2_frame_private_data_free(data_frame);
  } else {
    /* Unreachable */
    assert(0);
  }
  free(item->frame);
  free(item->aux_data);
}
Exemple #2
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;
}
Exemple #3
0
void test_nghttp2_frame_pack_altsvc(void)
{
  nghttp2_extension frame, oframe;
  nghttp2_ext_altsvc altsvc, oaltsvc;
  nghttp2_bufs bufs;
  nghttp2_buf *buf;
  size_t protocol_id_len, host_len, origin_len;
  uint8_t *protocol_id, *host, *origin;
  uint8_t *data;
  size_t datalen;
  int rv;
  size_t payloadlen;

  protocol_id_len = strlen("h2");
  host_len = strlen("h2.example.org");
  origin_len = strlen("www.example.org");

  datalen = protocol_id_len + host_len + origin_len;
  data = malloc(datalen);

  memcpy(data, "h2", protocol_id_len);
  protocol_id = data;

  memcpy(data + protocol_id_len, "h2.example.org", host_len);
  host = data + protocol_id_len;

  memcpy(data + protocol_id_len + host_len,
         "http://www.example.org", origin_len);
  origin = data + protocol_id_len + host_len;

  frame_pack_bufs_init(&bufs);

  frame.payload = &altsvc;

  nghttp2_frame_altsvc_init(&frame, 1000000007, 1u << 31, 4000,
                            protocol_id, protocol_id_len,
                            host, host_len, origin, origin_len);

  rv = nghttp2_frame_pack_altsvc(&bufs, &frame);

  CU_ASSERT(0 == rv);

  CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_MINLEN + datalen) ==
            nghttp2_bufs_len(&bufs));

  oframe.payload = &oaltsvc;

  CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));

  check_frame_header(NGHTTP2_ALTSVC_MINLEN + datalen,
                     NGHTTP2_EXT_ALTSVC, NGHTTP2_FLAG_NONE,
                     1000000007, &oframe.hd);
  CU_ASSERT(1u << 31 == oaltsvc.max_age);
  CU_ASSERT(4000 == oaltsvc.port);

  CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len);
  CU_ASSERT(memcmp(protocol_id, oaltsvc.protocol_id, protocol_id_len) == 0);

  CU_ASSERT(host_len == oaltsvc.host_len);
  CU_ASSERT(memcmp(host, oaltsvc.host, host_len) == 0);

  CU_ASSERT(origin_len == oaltsvc.origin_len);
  CU_ASSERT(memcmp(origin, oaltsvc.origin, origin_len) == 0);

  nghttp2_frame_altsvc_free(&oframe);
  nghttp2_frame_altsvc_free(&frame);

  memset(&oframe, 0, sizeof(oframe));
  memset(&oaltsvc, 0, sizeof(oaltsvc));

  buf = &bufs.head->buf;

  CU_ASSERT(buf->pos - buf->begin == 1);

  /* Check no origin case */

  payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len;
  nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3]));

  oframe.payload = &oaltsvc;

  CU_ASSERT(0 ==
            nghttp2_frame_unpack_altsvc_payload
            (&oframe,
             buf->pos + NGHTTP2_FRAME_HDLEN,
             NGHTTP2_ALTSVC_FIXED_PARTLEN,
             buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN,
             payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN));

  CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len);
  CU_ASSERT(host_len == oaltsvc.host_len);
  CU_ASSERT(0 == oaltsvc.origin_len);

  memset(&oframe, 0, sizeof(oframe));
  memset(&oaltsvc, 0, sizeof(oaltsvc));

  /* Check insufficient payload length for host */
  payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len - 1;
  nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3]));

  oframe.payload = &oaltsvc;

  CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR ==
            nghttp2_frame_unpack_altsvc_payload
            (&oframe,
             buf->pos + NGHTTP2_FRAME_HDLEN,
             NGHTTP2_ALTSVC_FIXED_PARTLEN,
             buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN,
             payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN));

  memset(&oframe, 0, sizeof(oframe));
  memset(&oaltsvc, 0, sizeof(oaltsvc));

  /* Check no host case */
  payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len;
  nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3]));
  buf->pos[NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN
           + protocol_id_len] = 0;

  oframe.payload = &oaltsvc;

  CU_ASSERT(0 ==
            nghttp2_frame_unpack_altsvc_payload
            (&oframe,
             buf->pos + NGHTTP2_FRAME_HDLEN,
             NGHTTP2_ALTSVC_FIXED_PARTLEN,
             buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN,
             payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN));

  CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len);
  CU_ASSERT(0 == oaltsvc.host_len);
  CU_ASSERT(0 == oaltsvc.origin_len);

  memset(&oframe, 0, sizeof(oframe));
  memset(&oaltsvc, 0, sizeof(oaltsvc));

  /* Check missing Host-Len */
  payloadlen = NGHTTP2_ALTSVC_FIXED_PARTLEN + protocol_id_len;
  nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3]));

  oframe.payload = &oaltsvc;

  CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR ==
            nghttp2_frame_unpack_altsvc_payload
            (&oframe,
             buf->pos + NGHTTP2_FRAME_HDLEN,
             NGHTTP2_ALTSVC_FIXED_PARTLEN,
             buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN,
             payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN));

  memset(&oframe, 0, sizeof(oframe));
  memset(&oaltsvc, 0, sizeof(oaltsvc));

  nghttp2_bufs_free(&bufs);
}