+/**
+ * Filter the inforecs in a single update
+ *
+ * @param filt The filter to apply
+ * @param upd The update to filter
+ */
+static void trps_filter_one_outbound_update(TR_FILTER *filt, TRP_UPD *upd)
+{
+ TRP_INFOREC *this=NULL, *next=NULL;
+ TR_FILTER_ACTION action=TR_FILTER_ACTION_REJECT;
+ TR_FILTER_TARGET *target=NULL;
+
+ for(this=trp_upd_get_inforec(upd); this!=NULL; this=next) {
+ next=this->next;
+ target= tr_filter_target_trp_inforec(NULL, upd, this);
+ if (target==NULL) {
+ /* TODO: signal that filtering failed. Until then, just filter everything and give an error message. */
+ tr_crit("trps_filter_one_outbound_update: Unable to allocate filter target, cannot apply filter!");
+ }
+ if ((target==NULL)
+ || (TR_FILTER_NO_MATCH==tr_filter_apply(target, filt, NULL, &action))
+ || (action!=TR_FILTER_ACTION_ACCEPT)) {
+ /* Either no filter matched or one matched and rejected this record.
+ * Also filter out record if we were unable to allocate a target. */
+ trp_upd_remove_inforec(upd, this); /* "this" is now invalid */
+ }
+ if (target!=NULL)
+ tr_filter_target_free(target);
+ }
+}
+
+/**
+ * May shuffle the update list.
+ *
+ * @param filters The filter set for the relevant TRP peer
+ * @param updates GPtrArray of updates to filter
+ */
+static void trps_filter_outbound_updates(TR_FILTER_SET *filters, GPtrArray *updates)
+{
+ TRP_UPD *upd=NULL;
+ guint ii=0;
+
+ /* Walk backward through the array so we can remove elements. Careful about loop
+ * termination - remember that ii is unsigned. */
+ for (ii=updates->len; ii>0; ii--) {
+ upd=g_ptr_array_index(updates, ii-1);
+ trps_filter_one_outbound_update(tr_filter_set_get(filters, TR_FILTER_TYPE_TRP_OUTBOUND), upd);
+ /* see if we removed all the records from this update */
+ if (trp_upd_num_inforecs(upd)==0)
+ g_ptr_array_remove_index_fast(updates, ii-1); /* does not preserve order at index ii or higher */
+ }
+}