congestion_control_build_ext_response(const circuit_params_t *our_params,
                                      const circuit_params_t *circ_params,
                                      uint8_t **msg_out, size_t *msg_len_out)
{
  ssize_t ret;
  uint8_t *request = NULL;
  trn_extension_t *ext = NULL;
  trn_extension_field_t *field = NULL;
  trn_extension_field_cc_t *cc_field = NULL;

  tor_assert(our_params);
  tor_assert(circ_params);
  tor_assert(msg_out);
  tor_assert(msg_len_out);

  ext = trn_extension_new();

  if (circ_params->cc_enabled) {
    /* Build the extension field that will hold the CC field. */
    field = trn_extension_field_new();
    trn_extension_field_set_field_type(field,
                                       TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE);

    /* Build the congestion control field response. */
    cc_field = trn_extension_field_cc_new();
    trn_extension_field_cc_set_sendme_inc(cc_field,
                                          our_params->sendme_inc_cells);

    ret = trn_extension_field_cc_encoded_len(cc_field);
    if (BUG(ret <= 0)) {
      trn_extension_field_free(field);
      goto err;
    }
    size_t field_len = ret;
    trn_extension_field_set_field_len(field, field_len);
    trn_extension_field_setlen_field(field, field_len);

    uint8_t *field_array = trn_extension_field_getarray_field(field);
    ret = trn_extension_field_cc_encode(field_array,
              trn_extension_field_getlen_field(field), cc_field);
    if (BUG(ret <= 0)) {
      trn_extension_field_free(field);
      goto err;
    }

    /* Build final extension. */
    trn_extension_add_fields(ext, field);
    trn_extension_set_num(ext, 1);
  }

  /* Encode extension. */
  ret = trn_extension_encoded_len(ext);
  if (BUG(ret < 0)) {
    goto err;
  }
  size_t request_len = ret;
  request = tor_malloc_zero(request_len);
  ret = trn_extension_encode(request, request_len, ext);
  if (BUG(ret < 0)) {
    tor_free(request);
    goto err;
  }
  *msg_out = request;
  *msg_len_out = request_len;

  /* We've just encoded the extension, clean everything. */
  ret = 0;

 err:
  trn_extension_free(ext);
  trn_extension_field_cc_free(cc_field);
  return (int)ret;
}
congestion_control_build_ext_response(const circuit_params_t *our_params,
                                      const circuit_params_t *circ_params,
                                      uint8_t **msg_out, size_t *msg_len_out)
{
  ssize_t ret;
  uint8_t *request = NULL;
  trn_extension_t *ext = NULL;
  trn_extension_field_t *field = NULL;
  trn_extension_field_cc_t *cc_field = NULL;

  tor_assert(our_params);
  tor_assert(circ_params);
  tor_assert(msg_out);
  tor_assert(msg_len_out);

  ext = trn_extension_new();

  if (circ_params->cc_enabled) {
     
    field = trn_extension_field_new();
    trn_extension_field_set_field_type(field,
                                       TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE);

     
    cc_field = trn_extension_field_cc_new();
    trn_extension_field_cc_set_sendme_inc(cc_field,
                                          our_params->sendme_inc_cells);

    ret = trn_extension_field_cc_encoded_len(cc_field);
    if (BUG(ret <= 0)) {
      trn_extension_field_free(field);
      goto err;
    }
    size_t field_len = ret;
    trn_extension_field_set_field_len(field, field_len);
    trn_extension_field_setlen_field(field, field_len);

    uint8_t *field_array = trn_extension_field_getarray_field(field);
    ret = trn_extension_field_cc_encode(field_array,
              trn_extension_field_getlen_field(field), cc_field);
    if (BUG(ret <= 0)) {
      trn_extension_field_free(field);
      goto err;
    }

     
    trn_extension_add_fields(ext, field);
    trn_extension_set_num(ext, 1);
  }

   
  ret = trn_extension_encoded_len(ext);
  if (BUG(ret < 0)) {
    goto err;
  }
  size_t request_len = ret;
  request = tor_malloc_zero(request_len);
  ret = trn_extension_encode(request, request_len, ext);
  if (BUG(ret < 0)) {
    tor_free(request);
    goto err;
  }
  *msg_out = request;
  *msg_len_out = request_len;

   
  ret = 0;

 err:
  trn_extension_free(ext);
  trn_extension_field_cc_free(cc_field);
  return (int)ret;
}