Annotation of embedaddon/strongswan/src/libipsec/ipsec_event_relay.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2012 Tobias Brunner
                      3:  * Copyright (C) 2012 Giuliano Grassi
                      4:  * Copyright (C) 2012 Ralf Sager
                      5:  * HSR Hochschule fuer Technik Rapperswil
                      6:  *
                      7:  * This program is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2 of the License, or (at your
                     10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     15:  * for more details.
                     16:  */
                     17: 
                     18: #include "ipsec_event_relay.h"
                     19: 
                     20: #include <library.h>
                     21: #include <utils/debug.h>
                     22: #include <threading/rwlock.h>
                     23: #include <collections/linked_list.h>
                     24: #include <collections/blocking_queue.h>
                     25: #include <processing/jobs/callback_job.h>
                     26: 
                     27: typedef struct private_ipsec_event_relay_t private_ipsec_event_relay_t;
                     28: 
                     29: /**
                     30:  * Private additions to ipsec_event_relay_t.
                     31:  */
                     32: struct private_ipsec_event_relay_t {
                     33: 
                     34:        /**
                     35:         * Public members
                     36:         */
                     37:        ipsec_event_relay_t public;
                     38: 
                     39:        /**
                     40:         * Registered listeners
                     41:         */
                     42:        linked_list_t *listeners;
                     43: 
                     44:        /**
                     45:         * Lock to safely access the list of listeners
                     46:         */
                     47:        rwlock_t *lock;
                     48: 
                     49:        /**
                     50:         * Blocking queue for events
                     51:         */
                     52:        blocking_queue_t *queue;
                     53: };
                     54: 
                     55: /**
                     56:  * Helper struct used to manage events in a queue
                     57:  */
                     58: typedef struct {
                     59: 
                     60:        /**
                     61:         * Type of the event
                     62:         */
                     63:        enum {
                     64:                IPSEC_EVENT_EXPIRE,
                     65:        } type;
                     66: 
                     67:        /**
                     68:         * Protocol of the SA
                     69:         */
                     70:        uint8_t protocol;
                     71: 
                     72:        /**
                     73:         * SPI of the SA, if any
                     74:         */
                     75:        uint32_t spi;
                     76: 
                     77:        /**
                     78:         * SA destination address
                     79:         */
                     80:        host_t *dst;
                     81: 
                     82:        /**
                     83:         * Additional data for specific event types
                     84:         */
                     85:        union {
                     86: 
                     87:                struct {
                     88:                        /** TRUE in case of a hard expire */
                     89:                        bool hard;
                     90:                } expire;
                     91: 
                     92:        } data;
                     93: 
                     94: } ipsec_event_t;
                     95: 
                     96: /**
                     97:  * Destroy IPsec event data
                     98:  */
                     99: static void ipsec_event_destroy(ipsec_event_t *event)
                    100: {
                    101:        event->dst->destroy(event->dst);
                    102:        free(event);
                    103: }
                    104: 
                    105: /**
                    106:  * Dequeue events and relay them to listeners
                    107:  */
                    108: static job_requeue_t handle_events(private_ipsec_event_relay_t *this)
                    109: {
                    110:        enumerator_t *enumerator;
                    111:        ipsec_event_listener_t *current;
                    112:        ipsec_event_t *event;
                    113: 
                    114:        event = this->queue->dequeue(this->queue);
                    115: 
                    116:        this->lock->read_lock(this->lock);
                    117:        enumerator = this->listeners->create_enumerator(this->listeners);
                    118:        while (enumerator->enumerate(enumerator, (void**)&current))
                    119:        {
                    120:                switch (event->type)
                    121:                {
                    122:                        case IPSEC_EVENT_EXPIRE:
                    123:                                if (current->expire)
                    124:                                {
                    125:                                        current->expire(event->protocol, event->spi, event->dst,
                    126:                                                                        event->data.expire.hard);
                    127:                                }
                    128:                                break;
                    129:                }
                    130:        }
                    131:        enumerator->destroy(enumerator);
                    132:        this->lock->unlock(this->lock);
                    133:        ipsec_event_destroy(event);
                    134:        return JOB_REQUEUE_DIRECT;
                    135: }
                    136: 
                    137: METHOD(ipsec_event_relay_t, expire, void,
                    138:        private_ipsec_event_relay_t *this, uint8_t protocol, uint32_t spi,
                    139:        host_t *dst, bool hard)
                    140: {
                    141:        ipsec_event_t *event;
                    142: 
                    143:        INIT(event,
                    144:                .type = IPSEC_EVENT_EXPIRE,
                    145:                .protocol = protocol,
                    146:                .spi = spi,
                    147:                .dst = dst->clone(dst),
                    148:                .data = {
                    149:                        .expire = {
                    150:                                .hard = hard,
                    151:                        },
                    152:                },
                    153:        );
                    154:        this->queue->enqueue(this->queue, event);
                    155: }
                    156: 
                    157: METHOD(ipsec_event_relay_t, register_listener, void,
                    158:        private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener)
                    159: {
                    160:        this->lock->write_lock(this->lock);
                    161:        this->listeners->insert_last(this->listeners, listener);
                    162:        this->lock->unlock(this->lock);
                    163: }
                    164: 
                    165: METHOD(ipsec_event_relay_t, unregister_listener, void,
                    166:        private_ipsec_event_relay_t *this, ipsec_event_listener_t *listener)
                    167: {
                    168:        this->lock->write_lock(this->lock);
                    169:        this->listeners->remove(this->listeners, listener, NULL);
                    170:        this->lock->unlock(this->lock);
                    171: }
                    172: 
                    173: METHOD(ipsec_event_relay_t, destroy, void,
                    174:        private_ipsec_event_relay_t *this)
                    175: {
                    176:        this->queue->destroy_function(this->queue, free);
                    177:        this->listeners->destroy(this->listeners);
                    178:        this->lock->destroy(this->lock);
                    179:        free(this);
                    180: }
                    181: 
                    182: /**
                    183:  * Described in header.
                    184:  */
                    185: ipsec_event_relay_t *ipsec_event_relay_create()
                    186: {
                    187:        private_ipsec_event_relay_t *this;
                    188: 
                    189:        INIT(this,
                    190:                .public = {
                    191:                        .expire = _expire,
                    192:                        .register_listener = _register_listener,
                    193:                        .unregister_listener = _unregister_listener,
                    194:                        .destroy = _destroy,
                    195:                },
                    196:                .listeners = linked_list_create(),
                    197:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                    198:                .queue = blocking_queue_create(),
                    199:        );
                    200: 
                    201:        lib->processor->queue_job(lib->processor,
                    202:                (job_t*)callback_job_create((callback_job_cb_t)handle_events, this,
                    203:                        NULL, (callback_job_cancel_t)return_false));
                    204: 
                    205:        return &this->public;
                    206: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>