mirror of
https://gitlab.xiph.org/xiph/icecast-common.git
synced 2024-12-04 14:46:31 -05:00
Feature: Added Interface that allows filtering and handling of objects
This commit is contained in:
parent
9527c26828
commit
f00e684932
@ -24,6 +24,7 @@ pkginclude_HEADERS = \
|
|||||||
include/igloo/io.h \
|
include/igloo/io.h \
|
||||||
include/igloo/stdio.h \
|
include/igloo/stdio.h \
|
||||||
include/igloo/filter.h \
|
include/igloo/filter.h \
|
||||||
|
include/igloo/objecthandler.h \
|
||||||
include/igloo/buffer.h \
|
include/igloo/buffer.h \
|
||||||
include/igloo/list.h \
|
include/igloo/list.h \
|
||||||
include/igloo/reportxml.h
|
include/igloo/reportxml.h
|
||||||
@ -35,6 +36,7 @@ libigloo_la_SOURCES = \
|
|||||||
src/io.c \
|
src/io.c \
|
||||||
src/stdio.c \
|
src/stdio.c \
|
||||||
src/filter.c \
|
src/filter.c \
|
||||||
|
src/objecthandler.c \
|
||||||
src/buffer.c \
|
src/buffer.c \
|
||||||
src/list.c \
|
src/list.c \
|
||||||
src/reportxml.c
|
src/reportxml.c
|
||||||
|
88
include/igloo/objecthandler.h
Normal file
88
include/igloo/objecthandler.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* Copyright (C) 2019 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBIGLOO__OBJECTHANDLER_H_
|
||||||
|
#define _LIBIGLOO__OBJECTHANDLER_H_
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Put a good description of this file here
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ro.h"
|
||||||
|
#include "interface.h"
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
|
/* About thread safety:
|
||||||
|
* This set of functions is thread safe.
|
||||||
|
*/
|
||||||
|
|
||||||
|
igloo_RO_FORWARD_TYPE(igloo_objecthandler_t);
|
||||||
|
|
||||||
|
/* Interface description */
|
||||||
|
typedef struct {
|
||||||
|
igloo_interface_base_ifdesc_t __base;
|
||||||
|
|
||||||
|
/* Whether the this backend is thread safe. */
|
||||||
|
int is_thread_safe;
|
||||||
|
|
||||||
|
/* Perform the actual test on the object. */
|
||||||
|
igloo_filter_result_t (*handle)(igloo_INTERFACE_BASIC_ARGS, igloo_ro_t object);
|
||||||
|
} igloo_objecthandler_ifdesc_t;
|
||||||
|
|
||||||
|
/* This creates a new objecthandler from a interface description and state.
|
||||||
|
* Parameters:
|
||||||
|
* ifdesc
|
||||||
|
* The interface description to use.
|
||||||
|
* backend_object
|
||||||
|
* A object used by the backend or igloo_RO_NULL.
|
||||||
|
* backend_userdata
|
||||||
|
* A userdata pointer used by the backend or NULL.
|
||||||
|
* name, associated
|
||||||
|
* See refobject_new().
|
||||||
|
*/
|
||||||
|
igloo_objecthandler_t * igloo_objecthandler_new(const igloo_objecthandler_ifdesc_t *ifdesc, igloo_ro_t backend_object, void *backend_userdata, const char *name, igloo_ro_t associated);
|
||||||
|
|
||||||
|
/* This handles a object according to the filter.
|
||||||
|
* Parameters:
|
||||||
|
* handler
|
||||||
|
* The handler to use.
|
||||||
|
* object
|
||||||
|
* The object to test.
|
||||||
|
* Returns:
|
||||||
|
* Whether the object was accepted by the handler or not.
|
||||||
|
*/
|
||||||
|
igloo_filter_result_t igloo_objecthandler_handle(igloo_objecthandler_t *handler, igloo_ro_t object);
|
||||||
|
|
||||||
|
/* This adds a filter to the handler.
|
||||||
|
* Parameters:
|
||||||
|
* handler
|
||||||
|
* The handler to add the filter to.
|
||||||
|
* filter
|
||||||
|
* The filter to add.
|
||||||
|
*/
|
||||||
|
int igloo_objecthandler_push_filter(igloo_objecthandler_t *handler, igloo_filter_t *filter);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ! _LIBIGLOO__OBJECTHANDLER_H_ */
|
@ -34,6 +34,7 @@ extern "C" {
|
|||||||
|
|
||||||
typedef struct igloo_io_tag igloo_io_t;
|
typedef struct igloo_io_tag igloo_io_t;
|
||||||
typedef struct igloo_filter_tag igloo_filter_t;
|
typedef struct igloo_filter_tag igloo_filter_t;
|
||||||
|
typedef struct igloo_objecthandler_tag igloo_objecthandler_t;
|
||||||
typedef struct igloo_buffer_tag igloo_buffer_t;
|
typedef struct igloo_buffer_tag igloo_buffer_t;
|
||||||
typedef struct igloo_list_tag igloo_list_t;
|
typedef struct igloo_list_tag igloo_list_t;
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ typedef union __attribute__ ((__transparent_union__)) {
|
|||||||
igloo_RO_TYPE(igloo_ro_base_t)
|
igloo_RO_TYPE(igloo_ro_base_t)
|
||||||
igloo_RO_TYPE(igloo_io_t)
|
igloo_RO_TYPE(igloo_io_t)
|
||||||
igloo_RO_TYPE(igloo_filter_t)
|
igloo_RO_TYPE(igloo_filter_t)
|
||||||
|
igloo_RO_TYPE(igloo_objecthandler_t)
|
||||||
igloo_RO_TYPE(igloo_buffer_t)
|
igloo_RO_TYPE(igloo_buffer_t)
|
||||||
igloo_RO_TYPE(igloo_list_t)
|
igloo_RO_TYPE(igloo_list_t)
|
||||||
igloo_RO_TYPE(igloo_reportxml_t)
|
igloo_RO_TYPE(igloo_reportxml_t)
|
||||||
|
166
src/objecthandler.c
Normal file
166
src/objecthandler.c
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/* Icecast
|
||||||
|
*
|
||||||
|
* This program is distributed under the GNU General Public License, version 2.
|
||||||
|
* A copy of this license is included with this source.
|
||||||
|
*
|
||||||
|
* Copyright 2019, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <igloo/ro.h>
|
||||||
|
#include <igloo/list.h>
|
||||||
|
#include <igloo/objecthandler.h>
|
||||||
|
#include <igloo/thread.h>
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
struct igloo_objecthandler_tag {
|
||||||
|
igloo_interface_base(objecthandler)
|
||||||
|
igloo_rwlock_t rwlock;
|
||||||
|
|
||||||
|
/* filters */
|
||||||
|
igloo_filter_t *filter_a;
|
||||||
|
igloo_filter_t *filter_b;
|
||||||
|
igloo_list_t *filter_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __free(igloo_ro_t self)
|
||||||
|
{
|
||||||
|
igloo_objecthandler_t *handler = igloo_RO_TO_TYPE(self, igloo_objecthandler_t);
|
||||||
|
|
||||||
|
igloo_thread_rwlock_wlock(&(handler->rwlock));
|
||||||
|
igloo_thread_rwlock_unlock(&(handler->rwlock));
|
||||||
|
igloo_thread_rwlock_destroy(&(handler->rwlock));
|
||||||
|
|
||||||
|
igloo_interface_base_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
igloo_RO_PUBLIC_TYPE(igloo_objecthandler_t,
|
||||||
|
igloo_RO_TYPEDECL_FREE(__free)
|
||||||
|
);
|
||||||
|
|
||||||
|
igloo_objecthandler_t * igloo_objecthandler_new(const igloo_objecthandler_ifdesc_t *ifdesc, igloo_ro_t backend_object, void *backend_userdata, const char *name, igloo_ro_t associated)
|
||||||
|
{
|
||||||
|
igloo_objecthandler_t *handler = igloo_interface_base_new(igloo_objecthandler_t, ifdesc, backend_object, backend_userdata, name, associated);
|
||||||
|
|
||||||
|
if (!handler)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
igloo_thread_rwlock_create(&(handler->rwlock));
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
igloo_filter_result_t igloo_objecthandler_handle(igloo_objecthandler_t *handler, igloo_ro_t object)
|
||||||
|
{
|
||||||
|
igloo_filter_result_t result = igloo_FILTER_RESULT_PASS;
|
||||||
|
int require_wlock = 0;
|
||||||
|
|
||||||
|
if (!igloo_RO_IS_VALID(handler, igloo_objecthandler_t))
|
||||||
|
return igloo_FILTER_RESULT_ERROR;
|
||||||
|
|
||||||
|
if (!handler->ifdesc->handle)
|
||||||
|
return igloo_FILTER_RESULT_ERROR;
|
||||||
|
|
||||||
|
/* Accessing handler->ifdesc->is_thread_safe is thread-safe. handler->filter_list is not, so we will recheck that later. */
|
||||||
|
if (!handler->ifdesc->is_thread_safe || handler->filter_list)
|
||||||
|
require_wlock = 1;
|
||||||
|
|
||||||
|
if (require_wlock) {
|
||||||
|
igloo_thread_rwlock_wlock(&(handler->rwlock));
|
||||||
|
} else {
|
||||||
|
igloo_thread_rwlock_rlock(&(handler->rwlock));
|
||||||
|
|
||||||
|
/* now re-check if we got a handler->filter_list now... If so, we re-lock.
|
||||||
|
* This is no problem as we can run with wlock anyway and handler->filter_list may not
|
||||||
|
* be reset to NULL as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (handler->filter_list) {
|
||||||
|
igloo_thread_rwlock_unlock(&(handler->rwlock));
|
||||||
|
require_wlock = 1;
|
||||||
|
igloo_thread_rwlock_wlock(&(handler->rwlock));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ok, now we are locked. Let's process input! */
|
||||||
|
|
||||||
|
if (handler->filter_list) {
|
||||||
|
igloo_list_iterator_storage_t iterator_storage;
|
||||||
|
igloo_list_iterator_t *iterator = igloo_list_iterator_start(handler->filter_list, &iterator_storage, sizeof(iterator_storage));
|
||||||
|
igloo_filter_t *filter;
|
||||||
|
|
||||||
|
for (; !igloo_RO_IS_NULL(filter = igloo_RO_TO_TYPE(igloo_list_iterator_next(iterator), igloo_filter_t)); ) {
|
||||||
|
result = igloo_filter_test(filter, object);
|
||||||
|
igloo_ro_unref(filter);
|
||||||
|
if (result != igloo_FILTER_RESULT_PASS) {
|
||||||
|
igloo_list_iterator_end(iterator);
|
||||||
|
igloo_thread_rwlock_unlock(&(handler->rwlock));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
igloo_list_iterator_end(iterator);
|
||||||
|
} else {
|
||||||
|
if (handler->filter_a)
|
||||||
|
result = igloo_filter_test(handler->filter_a, object);
|
||||||
|
|
||||||
|
if (result == igloo_FILTER_RESULT_PASS && handler->filter_b)
|
||||||
|
result = igloo_filter_test(handler->filter_b, object);
|
||||||
|
|
||||||
|
if (result != igloo_FILTER_RESULT_PASS) {
|
||||||
|
igloo_thread_rwlock_unlock(&(handler->rwlock));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = handler->ifdesc->handle(igloo_INTERFACE_BASIC_CALL(handler), object);
|
||||||
|
|
||||||
|
igloo_thread_rwlock_unlock(&(handler->rwlock));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int igloo_objecthandler_push_filter(igloo_objecthandler_t *handler, igloo_filter_t *filter)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!igloo_RO_IS_VALID(handler, igloo_objecthandler_t) || !igloo_RO_IS_VALID(filter, igloo_filter_t))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
igloo_thread_rwlock_wlock(&(handler->rwlock));
|
||||||
|
if (!handler->filter_list && handler->filter_a && handler->filter_b) {
|
||||||
|
handler->filter_list = igloo_ro_new(igloo_list_t);
|
||||||
|
if (!handler->filter_list) {
|
||||||
|
igloo_thread_rwlock_unlock(&(handler->rwlock));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
igloo_list_set_type(handler->filter_list, igloo_filter_t);
|
||||||
|
igloo_list_preallocate(handler->filter_list, 3);
|
||||||
|
|
||||||
|
igloo_list_push(handler->filter_list, handler->filter_a);
|
||||||
|
igloo_ro_unref(handler->filter_a);
|
||||||
|
handler->filter_a = NULL;
|
||||||
|
igloo_list_push(handler->filter_list, handler->filter_b);
|
||||||
|
igloo_ro_unref(handler->filter_b);
|
||||||
|
handler->filter_b = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler->filter_list) {
|
||||||
|
ret = igloo_list_push(handler->filter_list, filter);
|
||||||
|
} else {
|
||||||
|
ret = igloo_ro_ref(filter);
|
||||||
|
if (ret == 0) {
|
||||||
|
if (!handler->filter_a) {
|
||||||
|
handler->filter_a = filter;
|
||||||
|
} else {
|
||||||
|
handler->filter_b = filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
igloo_thread_rwlock_unlock(&(handler->rwlock));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user