return -1;
}
}
+
+/**
+ * If there is an extension field of type `ext_type` in `ext`,
+ * return that field. Otherwise return NULL.
+ */
+const trn_extension_field_t *
+trn_extension_find(const trn_extension_t *ext, uint8_t ext_type)
+{
+ IF_BUG_ONCE(!ext) {
+ return NULL;
+ }
+ size_t n_fields = trn_extension_get_num(ext);
+ if (n_fields == 0)
+ return NULL;
+
+ for (unsigned i = 0; i < n_fields; ++i) {
+ const trn_extension_field_t *field = trn_extension_getconst_fields(ext, i);
+ IF_BUG_ONCE(field == NULL) {
+ return NULL;
+ }
+ if (trn_extension_field_get_field_type(field) == ext_type) {
+ return field;
+ }
+ }
+
+ return NULL;
+}
#define server_onion_keys_free(keys) \
FREE_AND_NULL(server_onion_keys_t, server_onion_keys_free_, (keys))
+struct trn_extension_st;
+struct trn_extension_field_st;
+const struct trn_extension_field_st *trn_extension_find(
+ const struct trn_extension_st *ext,
+ uint8_t ext_type);
+
#endif /* !defined(TOR_ONION_CRYPTO_H) */
{
ssize_t ret = 0;
trn_extension_t *ext = NULL;
- size_t num_fields = 0;
/* Parse extension from payload. */
ret = trn_extension_parse(&ext, msg, msg_len);
goto end;
}
- /* No extension implies no support for congestion control. In this case, we
- * simply return 0 to indicate CC is disabled. */
- if ((num_fields = trn_extension_get_num(ext)) == 0) {
+ if (trn_extension_find(ext, TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST) == NULL) {
+ /* No extension implies no support for congestion control. In this case, we
+ * simply return 0 to indicate CC is disabled. */
ret = 0;
- goto end;
- }
-
- /* Go over all fields. If any field is TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST,
- * then congestion control is enabled. Ignore unknown fields. */
- for (size_t f = 0; f < num_fields; f++) {
- const trn_extension_field_t *field = trn_extension_get_fields(ext, f);
- if (field == NULL) {
- ret = -1;
- goto end;
- }
-
+ } else {
/* For congestion control to be enabled, we only need the field type. */
- if (trn_extension_field_get_field_type(field) ==
- TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST) {
- ret = 1;
- break;
- }
+ ret = 1;
}
end:
circuit_params_t *params_out)
{
ssize_t ret = 0;
- size_t num_fields = 0;
trn_extension_t *ext = NULL;
+ const trn_extension_field_t *field = NULL;
trn_extension_field_cc_t *cc_field = NULL;
/* We will only accept this response (and this circuit) if sendme_inc
goto end;
}
- if ((num_fields = trn_extension_get_num(ext)) == 0) {
- ret = 0;
- goto end;
- }
-
- /* Go over all fields. If any field is TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE,
- * then congestion control is enabled. Ignore unknown fields. */
- for (size_t f = 0; f < num_fields; f++) {
- const trn_extension_field_t *field = trn_extension_get_fields(ext, f);
- if (field == NULL) {
- ret = -1;
- goto end;
- }
-
- /* Only examine TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE; ignore other fields */
- if (trn_extension_field_get_field_type(field) ==
- TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE) {
+ field = trn_extension_find(ext, TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE);
+ if (field == 0) {
+ ret = 0;
+ } else {
/* Parse the field into the congestion control field. */
ret = trn_extension_field_cc_parse(&cc_field,
trn_extension_field_getconstarray_field(field),
/* All good. Get value and break */
params_out->sendme_inc_cells = sendme_inc_cells;
ret = 1;
- break;
- }
}
end: